Semantyka i weryfikacja programów/Ćwiczenia 4: Różnice pomiędzy wersjami
Nie podano opisu zmian |
Nie podano opisu zmian |
||
Linia 1: | Linia 1: | ||
== | == Zawarto¶æ == | ||
Napiszemy | Napiszemy semantykê naturaln± jêzyka wyra¿eñ, | ||
rozwa¿ymy strategiê gorliw± (jak na wcze¶niejszych zajêciach, | |||
w semantyce | w semantyce ma³ych kroków) i leniw±. | ||
Rozwa¿ymy i statyczne i dynamiczne wi±zanie identyfikatorów. | |||
Nastêpnie rozszerzymy ten jêzyk o lambda-abstrakcjê i aplikacjê, | |||
otrzymuj±c prosty jêzyk funkcyjny. | |||
== | == Ró¿ne semantyki naturalne wyra¿eñ == | ||
Linia 17: | Linia 17: | ||
Napisz | Napisz semantykê du¿ych kroków | ||
dla | dla jêzyka wyra¿eñ, którego semantykê ma³o-krokow± | ||
napisali¶my na jednych z poprzednich æwiczeñ: | |||
<math> | <math> | ||
Linia 44: | Linia 44: | ||
<div class="mw-collapsible mw-made=collapsible mw-collapsed"><div class="mw-collapsible-content" style="display:none"> | <div class="mw-collapsible mw-made=collapsible mw-collapsed"><div class="mw-collapsible-content" style="display:none"> | ||
Przypomnijmy, | Przypomnijmy, ¿e zbiór stanów to | ||
<math> | <math> | ||
\mathbf{State} \, = \, \mathbf{Var} \to_{\mathrm{fin}} \mathbf{Num} | \mathbf{State} \, = \, \mathbf{Var} \to_{\mathrm{fin}} \mathbf{Num} | ||
</math> | </math> | ||
Nasze tranzycje | Nasze tranzycje bêd± postaci <math>e, s \,\longrightarrow\, n</math>, gdzie | ||
<math>e \in \mathbf{Exp}, s \in \mathbf{State}, n \in \mathbf{Num}</math>. | <math>e \in \mathbf{Exp}, s \in \mathbf{State}, n \in \mathbf{Num}</math>. | ||
Oto | Oto regu³y semantyki naturalnej. | ||
<math> | <math> | ||
Linia 81: | Linia 81: | ||
</math> | </math> | ||
Zwróæmy uwagê na fakt, ¿e prawid³owe odwzorowanie zasiêgu deklaracji <math>x = e_1</math> nie predstawia | |||
w semantyce naturalnej | w semantyce naturalnej ¿adnych trudno¶ci, w przeciwieñstwie do | ||
semantyki | semantyki ma³ych kroków. | ||
</div></div> | </div></div> | ||
Linia 92: | Linia 92: | ||
Zmodyfikuj | Zmodyfikuj semantykê z poprzedniego zadania, aby uzyskaæ | ||
'' | ''leniw±'' ewaluacjê wyra¿eñ, zgodnie z dyrektyw±: nie obliczaj | ||
wyra¿enia o ile jego wynik nie jest potrzebny | |||
(albo: obliczaj | (albo: obliczaj warto¶æ wyra¿enia dopiero wtedy, gdy jego wynik jest | ||
naprawdê potrzebny). Spójrzmy na przyk³ad: | |||
<math> | <math> | ||
Linia 102: | Linia 102: | ||
</math> | </math> | ||
Wed³ug semantyki z poprzedniego zadania wyra¿nie to nie ma warto¶ci, | |||
bo w deklaracji <math>y = y+y</math> jest | bo w deklaracji <math>y = y+y</math> jest odwo³anie do niezainicjowanej | ||
zmiennej. | zmiennej. | ||
Natomiast w semantyce leniwej | Natomiast w semantyce leniwej wyra¿enie to obliczy siê do warto¶ci | ||
<math>14</math>, | <math>14</math>, gdy¿ wyra¿enie <math>y+y</math> nie bêdzie wogóle obliczane. | ||
Bêdzie tak dlatego, ¿e w wyra¿eniu <math>x+x</math> nie ma odwo³añ do | |||
zmiennej <math>y</math>. | zmiennej <math>y</math>. | ||
}} | }} | ||
Linia 116: | Linia 116: | ||
<div class="mw-collapsible mw-made=collapsible mw-collapsed"><div class="mw-collapsible-content" style="display:none"> | <div class="mw-collapsible mw-made=collapsible mw-collapsed"><div class="mw-collapsible-content" style="display:none"> | ||
Semantyka ''leniwa'' | Semantyka ''leniwa'' bêdzie bardzo podobna do tej z poprzedniego zadania. | ||
Zasadnicza | Zasadnicza ró¿nica dotyczy informacji przechowywanej w stanie. | ||
Dotychczas <math>s(x)</math> | Dotychczas <math>s(x)</math> nala¿a³ do zbioru <math>\in \mathbf{Num}</math>, gdy¿ podwyra¿enie <math>e</math> w | ||
<math>\mathbf{let}\, x = e \,\mathbf{in}\, \ldots</math> | <math>\mathbf{let}\, x = e \,\mathbf{in}\, \ldots</math> oblicza³o sie natychmiast. | ||
Je¶li chcemy opó¿nic obliczenie tego podwyra¿enia, to w | |||
<math>s(x)</math> | <math>s(x)</math> powinni¶my zapamiêtaæ ca³e (nieobliczone) wyra¿enie <math>e</math> | ||
wraz ze stanem | wraz ze stanem bie¿±cym. | ||
Czyli | Czyli | ||
Linia 129: | Linia 129: | ||
</math> | </math> | ||
Np. odpowiednia | Np. odpowiednia regu³a dla wyra¿enia <math>\mathbf{let}\,</math> w semantyce | ||
ma³ych kroków mog³aby wygl±daæ nastêpuj±co: | |||
<math> | <math> | ||
Linia 136: | Linia 136: | ||
</math> | </math> | ||
Czyli stan zawiera, dla | Czyli stan zawiera, dla ka¿dej zmiennej, parê | ||
( | (wyra¿enie definiuj±ce, stan w momencie deklaracji). | ||
Uwa¿nego czytelnika zapewne zaniepokoi³ fakt, ¿e <math>\mathbf{State}</math> | |||
stoi zarówno po lewej jak i po prawej stronie równania | stoi zarówno po lewej jak i po prawej stronie równania | ||
<math> | <math> | ||
\mathbf{State} \, = \, \mathbf{Var} \to_{\mathrm{fin}} \mathbf{Exp} \times \mathbf{State}. | \mathbf{State} \, = \, \mathbf{Var} \to_{\mathrm{fin}} \mathbf{Exp} \times \mathbf{State}. | ||
</math> | </math> | ||
Równie¿ zapis <math>s[x \mapsto (e_1, s)]</math> mo¿e wzbudziæ niepokój, | |||
gdy¿ sugeruje on, i¿ <math>s(x)</math> zawiera, jako jeden z elementów pary, | |||
obiekt ''tego samego typu'' co <math>s</math>. | obiekt ''tego samego typu'' co <math>s</math>. | ||
Formalnego | Formalnego rozwi±zania tego typu dylematów dostarcza teoria dziedzin. | ||
Natomiast na | Natomiast na u¿ytek semantyki operacyjnej wystarczy, je¶li | ||
uznamy, | uznamy, i¿ równanie | ||
<math> | <math> | ||
\mathbf{State} \, = \, \mathbf{Var} \to_{\mathrm{fin}} \mathbf{Exp} \times \mathbf{State} | \mathbf{State} \, = \, \mathbf{Var} \to_{\mathrm{fin}} \mathbf{Exp} \times \mathbf{State} | ||
</math> | </math> | ||
stanowi skrótowy zapis | stanowi skrótowy zapis nastêpuj±cej definicji. | ||
Zdefiniujmy <math>\mathbf{State}_0, \mathbf{State}_1, \ldots</math> | Zdefiniujmy <math>\mathbf{State}_0, \mathbf{State}_1, \ldots</math> nastêpuj±co: | ||
<math> | <math> | ||
Linia 164: | Linia 164: | ||
</math> | </math> | ||
i przyjmijmy, | i przyjmijmy, ¿e | ||
<math> | <math> | ||
Linia 170: | Linia 170: | ||
</math> | </math> | ||
Tranzycje | Tranzycje bêd± znów postaci: | ||
<math> | <math> | ||
e, s \,\longrightarrow\, n. | e, s \,\longrightarrow\, n. | ||
</math> | </math> | ||
Podamy tylko | Podamy tylko regu³y dla wyst±pienia zmiennej i dla wyra¿enia | ||
<math>\mathbf{let}\,</math>. | <math>\mathbf{let}\,</math>. Regu³y dla pozosta³ych konstrukcji jêzyka pozostaj± praktycznie bez zmian. | ||
<math> | <math> | ||
Linia 191: | Linia 191: | ||
{{cwiczenie|3 | {{cwiczenie|3 (semantyka dynamiczna)|cw3| | ||
Rozwa¿my teraz zupe³nie inny mechanizm wi±zania identyfikatorów, | |||
zwany '' | zwany ''wi±zaniem dynamicznym''. | ||
Dla | Dla odró¿nienia, dotychczasowy sposób wi±zania (widoczno¶ci) | ||
identyfikatorów | identyfikatorów bêdziemy nazywaæ ''wi±zaniem statycznym''. | ||
Oto | Oto przyk³adowe wyra¿enie: | ||
<math> | <math> | ||
Linia 204: | Linia 204: | ||
</math> | </math> | ||
które nie ma | które nie ma warto¶ci w pustym stanie pocz±tkowym, | ||
wed³ug semantyk z poprzednich zadañ, poniewa¿ | |||
odwo³anie do zmiennej <math>x</math> w deklaracji <math>y = x+1</math> | |||
jest niepoprawne. | jest niepoprawne. | ||
Tak samo jest nawet w semantyce leniwej, | Tak samo jest nawet w semantyce leniwej, gdy¿ warto¶æ zmiennej | ||
<math>y</math> | <math>y</math> bêdzie w koñcu policzona, i bêdzie wymaga³a odwo³ania do <math>x | ||
</math> w stanie pustym. | </math> w stanie pustym. | ||
Natomiast | Natomiast wyobra¿my sobie, ¿e zmieniamy semantykê leniw± nastêpuj±co: | ||
odwo³anie do zmiennej <math>x</math> podczas obliczania warto¶ci <math>y</math> | |||
bêdzie odnosi³o siê nie do stanu w momencie deklaracji <math>y</math>, | |||
ale do stanu w momencie '' | ale do stanu w momencie ''odwo³ania'' do <math>y</math>. | ||
Jest to | Jest to do¶æ rewolucyjna zmiana, zapewne sprzeczna z intuicjami | ||
programisty (statyczne | programisty (statyczne regu³y widoczno¶ci zamieniamy na | ||
''dynamiczne''). W | ''dynamiczne''). W szczególno¶ci powy¿sze wyra¿enie policzy siê | ||
w semantyce dynamicznej do | w semantyce dynamicznej do warto¶ci 11, poniewa¿ stan w momencie | ||
odwo³ania do zmiennej <math>y</math> przypisuje zmiennej <math>x</math> | |||
warto¶æ 10 ! | |||
Napisz | Napisz semantykê naturaln± dla wi±zania dynamicznego. | ||
}} | }} | ||
Linia 231: | Linia 231: | ||
<div class="mw-collapsible mw-made=collapsible mw-collapsed"><div class="mw-collapsible-content" style="display:none"> | <div class="mw-collapsible mw-made=collapsible mw-collapsed"><div class="mw-collapsible-content" style="display:none"> | ||
Teraz w stanie wystarczy | Teraz w stanie wystarczy przechowywaæ ''wyra¿enie'' definiuj±ce | ||
warto¶æ danej zmiennej: | |||
<math> | <math> | ||
Linia 238: | Linia 238: | ||
</math> | </math> | ||
Nie potrzebujemy | Nie potrzebujemy zapamiêtywaæ stanu, w którym byli¶my w momencie | ||
deklaracji. Do obliczenia | deklaracji. Do obliczenia zapamiêtanego wyra¿enia u¿yjemy stanu, | ||
w którym | w którym bêdziemy w momencie odwo³ania do danej zmiennej. | ||
Znów podajemy tylko | Znów podajemy tylko regu³y dla wyst±pienia zmiennej i dla | ||
wyra¿enia <math>\mathbf{let}\,</math>, gdy¿ pozosta³e regu³y pozostaj± bez zmian | |||
<math> | <math> | ||
Linia 254: | Linia 254: | ||
</math> | </math> | ||
'''Pytanie:''' czy <math>\mathbf{let}\, x = x+1 \,\mathbf{in}\, x</math> oblicza | '''Pytanie:''' czy <math>\mathbf{let}\, x = x+1 \,\mathbf{in}\, x</math> oblicza siê do jakiej¶ | ||
warto¶ci w stanie <math>\emptyset</math>? | |||
</div></div> | </div></div> | ||
Linia 261: | Linia 261: | ||
== Prosty | == Prosty jêzyk funkcyjny == | ||
{{cwiczenie|4 (przekazywanie parametru przez | {{cwiczenie|4 (przekazywanie parametru przez warto¶æ)|cw4| | ||
Rozwa¿my prosty jêzyk funkcyjny <math>F</math> rozszerzaj±cy | |||
jêzyk wyra¿eñ z poprzednich zadañ nastêpuj±co: | |||
<math> | <math> | ||
Linia 277: | Linia 277: | ||
</math> | </math> | ||
''Lambda-abstrakcja'' <math>\lambda x.e</math> reprezentuje | ''Lambda-abstrakcja'' <math>\lambda x.e</math> reprezentuje anonimow± | ||
( | (nienazwan±) funkcjê jednoargumentow±, natomiast wyra¿enie | ||
<math>e_1(e_2)</math> to ''aplikacja'' <math>e_1</math> do <math>e_2</math> ( | <math>e_1(e_2)</math> to ''aplikacja'' <math>e_1</math> do <math>e_2</math> (wyra¿enie | ||
<math>e_1</math> powinno zatem | <math>e_1</math> powinno zatem obliczaæ siê do funkcji). | ||
Np. | Np. | ||
Linia 287: | Linia 287: | ||
</math> | </math> | ||
Przyjmijmy | Przyjmijmy statyczn± widoczno¶æ identyfikatorów. | ||
Mo¿liwe s± ró¿ne mechanizmy przekazywania parametrów. | |||
Na razie wybierzmy mechanizm przekazywania przez | Na razie wybierzmy mechanizm przekazywania przez warto¶æ, | ||
zapewne doskonale znany Czytelnikowi: | zapewne doskonale znany Czytelnikowi: wyra¿enie | ||
bêd±ce parametrem aktualnym jest obliczane przed wywo³aniem funkcji, | |||
czyli w stanie, w którym | czyli w stanie, w którym jeste¶my z momencie wywo³ania funkcji. | ||
Zaproponuj | Zaproponuj semantykê naturaln± dla tego jêzyka | ||
dla obydwu mechanizmów przekazywania parametrów. | dla obydwu mechanizmów przekazywania parametrów. | ||
}} | }} | ||
Linia 303: | Linia 303: | ||
<div class="mw-collapsible mw-made=collapsible mw-collapsed"><div class="mw-collapsible-content" style="display:none"> | <div class="mw-collapsible mw-made=collapsible mw-collapsed"><div class="mw-collapsible-content" style="display:none"> | ||
Zauwa¿my, ¿e oprócz deklaracji zmiennych, równie¿ | |||
machanizm przekazywania parametru do funkcji wymaga zmiany stanu. | machanizm przekazywania parametru do funkcji wymaga zmiany stanu. | ||
Tranzycje | Tranzycje bêd± postaci | ||
<math> | <math> | ||
Linia 312: | Linia 312: | ||
</math> | </math> | ||
gdzie <math>v</math> reprezentuje | gdzie <math>v</math> reprezentuje warto¶æ, do której oblicza siê program <math>e</math>. | ||
Z tym, | Z tym, ¿e warto¶ciami bêd± nie tylko warto¶ci liczbowe. Na przyk³ad | ||
<math> | <math> | ||
\lambda x. x | \lambda x. x | ||
</math> | </math> | ||
oblicza | oblicza siê równie¿ do pewnej warto¶æ, która w tym przypadku powinna reprezentowaæ | ||
jako¶ ''funkcjê'' iudentyczno¶ciow±. Wystarczaj±c± reprezentacj± | |||
funkcji | funkcji bêdzie trójka: | ||
<math>\langle x, e, s \rangle</math>, | <math>\langle x, e, s \rangle</math>, | ||
gdzie <math>x</math> jest | gdzie <math>x</math> jest nazw± parametru formalnego, <math>e</math> jest cia³em | ||
funkcji a <math>s</math> jest stanem, w którym | funkcji a <math>s</math> jest stanem, w którym nale¿y obliczaæ warto¶æ | ||
funkcji po zaaplikowaniu do | funkcji po zaaplikowaniu do jakiego¶ parametru aktualnego. | ||
Oto prosty | Oto prosty przyk³ad pokazuj±cy, dlaczego powinni¶my pamiêtaæ stan: | ||
<math> | <math> | ||
Linia 330: | Linia 330: | ||
</math> | </math> | ||
Funkcja <math>f</math> | Funkcja <math>f</math> zwiêksza parametr aktualny o <math>x</math>. | ||
Program oblicza | Program oblicza siê do warto¶ci <math>17</math>, gdy¿ wyst±pienie | ||
zmiennej <math>x</math> w ciele funkcji <math>f</math> | zmiennej <math>x</math> w ciele funkcji <math>f</math> wi±¿e statycznie | ||
a zatem odnosi | a zatem odnosi siê zawsze do deklaracji <math>x = 7</math>, mimo tego, | ||
¿e w momencie wywo³ania tej funkcji warto¶æ zmiennej <math>x</math> | |||
wynosi <math>8</math>. | wynosi <math>8</math>. | ||
Oto jedyna | Oto jedyna regu³a, jakiej bêdziemy potrzebowaæ dla lambda-abstrakcji: | ||
<math> | <math> | ||
Linia 343: | Linia 343: | ||
</math> | </math> | ||
Nie potrafimy | Nie potrafimy zrobiæ z funkcj± <math>\lambda x. e</math> nic innego jak | ||
zapamiêtaæ informacjê niezbêdn± do obliczania jej warto¶ci | |||
w | w przyszlo¶ci. | ||
Zatem zbiór | Zatem zbiór warto¶ci bedzie nastêpuj±cy: | ||
<math> | <math> | ||
Linia 352: | Linia 352: | ||
</math> | </math> | ||
a zbiór stanów <math>\mathbf{State}</math> | a zbiór stanów <math>\mathbf{State}</math> okre¶lony jest nastêpuj±cym równaniem: | ||
<math> | <math> | ||
Linia 358: | Linia 358: | ||
</math> | </math> | ||
Zacznijmy od | Zacznijmy od sta³ych, zmiennych i lambda-abstrakcji: | ||
<math> | <math> | ||
Linia 368: | Linia 368: | ||
</math> | </math> | ||
W regule dla zmiennej, <math>v</math> oznacza albo | W regule dla zmiennej, <math>v</math> oznacza albo warto¶æ liczbow± albo | ||
funkcyjn±. Pomijamy regu³ê dla dodawania, bo jest ona identyczna | |||
jak dla gorliwej semantyki | jak dla gorliwej semantyki wyra¿eñ. | ||
Regu³a dla <math>\mathbf{let}\, x = e_1 \,\mathbf{in}\, e_2</math> bêdzie prawie taka sama jak dla wyra¿eñ, | |||
z | z t± ró¿nic±, ¿e wyra¿enie <math>e_1</math> definiuj±ce warto¶æ zmiennej <math>x</math> | ||
mo¿e siê teraz obliczaæ do warto¶ci funkcyjnej, np. | |||
<math>\mathbf{let}\, x = (\lambda y.y+y) \,\mathbf{in}\, x(0)</math>. | <math>\mathbf{let}\, x = (\lambda y.y+y) \,\mathbf{in}\, x(0)</math>. | ||
Linia 381: | Linia 381: | ||
</math> | </math> | ||
Pozosta³a nam ju¿ tylko regu³a dla aplikacji: najpierw oblicz funkcjê; | |||
nastêpnie oblicz warto¶æ parametru aktualnego; wreszcie przeka¿ j± | |||
do | do cia³a funkcji (czyli oblicz cia³o funkcji w zmodyfikowanym stanie): | ||
<math> | <math> | ||
Linia 392: | Linia 392: | ||
</math> | </math> | ||
Zwróæmy uwagê na wymóg, ¿e <math>e_1</math> oblicza siê do warto¶ci | |||
funkcyjnej <math>\langle x, e, s' \rangle</math>. | funkcyjnej <math>\langle x, e, s' \rangle</math>. | ||
W | W szczególno¶ci np. wyra¿enie <math>7(3+4)</math> jest | ||
niepoprawne. Natomiast parametr aktualny nie musi | niepoprawne. Natomiast parametr aktualny nie musi byæ liczb±, mo¿e byæ | ||
funkcj±, np. w programie: | |||
<math> | <math> | ||
Linia 403: | Linia 403: | ||
</math> | </math> | ||
który oblicza | który oblicza siê do warto¶ci <math>8</math>. | ||
</div></div> | </div></div> | ||
Linia 409: | Linia 409: | ||
{{cwiczenie|5 (przekazywanie parametru przez | {{cwiczenie|5 (przekazywanie parametru przez nazwê)|cw5| | ||
Zaproponuj ''leniw±'' semantykê jêzyka <math>F</math> z mechnizmem | |||
przekazywanie parametru ''przez | przekazywanie parametru ''przez nazwê''. | ||
Mechanizm ten stanowi leniwy odpowiednik przekazywania przez | Mechanizm ten stanowi leniwy odpowiednik przekazywania przez warto¶æ: | ||
nie obliczamy | nie obliczamy wyra¿enia bêd±cego parametrem aktualnym, a zamiast | ||
jego | jego warto¶ci przekazujemy do funkcji to wyra¿enie wraz ze | ||
stanem z miejsca | stanem z miejsca wywo³ania funkcji. | ||
To ten stan bedzie brany pod | To ten stan bedzie brany pod uwagê, gdy obliczana bêdzie | ||
warto¶æ parametru, tzn. przy odwo³aniu w ciele funkcji do | |||
parametru formalnego. Oto | parametru formalnego. Oto przyk³ad programu: | ||
<math> | <math> | ||
Linia 426: | Linia 426: | ||
</math> | </math> | ||
który w stanie pustym (wszystkie zmienne | który w stanie pustym (wszystkie zmienne nieokre¶lone) | ||
nie ma | nie ma warto¶ci przy przekazywaniu parametru przez warto¶æ | ||
(bo | (bo odwo³anie do zmiennej <math>y</math> jest niepoprawne) a oblicza siê | ||
do | do warto¶ci <math>7</math> je¶li wybierzemy mechanizm przekazywania przez | ||
nazwê. | |||
}} | }} | ||
Linia 438: | Linia 438: | ||
<div class="mw-collapsible mw-made=collapsible mw-collapsed"><div class="mw-collapsible-content" style="display:none"> | <div class="mw-collapsible mw-made=collapsible mw-collapsed"><div class="mw-collapsible-content" style="display:none"> | ||
Zbiór | Zbiór warto¶ci <math>\mathbf{Values}</math> stoj±cych po prawej stronie symbolu <math>\,\longrightarrow\,</math> | ||
bêdzie taki sam jak w poprzednim zadaniu. | |||
Natomiast zbiór stanów taki sam jak w semantyce leniwej | Natomiast zbiór stanów taki sam jak w semantyce leniwej wyra¿eñ: | ||
<math> | <math> | ||
Linia 446: | Linia 446: | ||
</math> | </math> | ||
Podamy tylko trzy | Podamy tylko trzy regu³y: dla wyst±pienie zmiennej, deklaracji <math>\mathbf{let}\,</math> | ||
i aplikacji -- wszystkie | i aplikacji -- wszystkie pozosta³e regu³y pozostaj± w³a¶ciwie | ||
takie same jak w poprzednim zadaniu. | takie same jak w poprzednim zadaniu. | ||
Linia 466: | Linia 466: | ||
</math> | </math> | ||
Podstawowa | Podstawowa ró¿nica w ostatnej regule w porównaniu do poprzedniego | ||
zadania to ''brak ewaluacji'' parametru aktualnego <math>e_2</math>. | zadania to ''brak ewaluacji'' parametru aktualnego <math>e_2</math>. | ||
Zwróæmy te¿ uwagê na wyra¿enie | |||
<math>s'[x \mapsto (e_2, s)]</math>, w którym <math>s \neq s'</math>. | <math>s'[x \mapsto (e_2, s)]</math>, w którym <math>s \neq s'</math>. | ||
Stany, których | Stany, których potrzebowali¶my dotychczas podczas poprzednich zajêæ, mia³y zawsze postaæ | ||
<math>s[x \mapsto (e, s)</math>. | <math>s[x \mapsto (e, s)</math>. | ||
Linia 480: | Linia 480: | ||
{{cwiczenie|1|cw1.dom| | |||
Podaj | Podaj przyk³ad wyra¿enia takiego, które: | ||
* ma | * ma warto¶æ w semantyce statycznej i dynamicznej, ale w ka¿dej inn± | ||
* ma | * ma warto¶æ w semantyce leniwej a nie ma w dynamicznej | ||
* ma | * ma warto¶æ w semantyce dynamicznej a nie ma w leniwej. | ||
}} | |||
{{cwiczenie|2|cw2.dom| | |||
W semantyce leniwej wyra¿eñ, je¶li jest wiele odwo³añ do jakiej¶ | |||
zmiennej, to obliczenie warto¶ci tej zmiennej nast±pi za ka¿dym razem | |||
od nowa. Zmodyfikuj tê semantykê tak, aby warto¶æ ta by³a obliczana | |||
''co najwy¿ej'' raz. | |||
Zatem po pierwszym odwo³aniu do zmiennej, jej obliczona warto¶æ | |||
powinna zostaæ umieszczona w stanie, zastêpuj±c parê (wyra¿enie, stan). | |||
}} | |||
{{cwiczenie|3|cw3.dom| | |||
Zaproponuj ''dynamiczne'' odpowiedniki obydwu ''statycznych'' semantyk dla | Zaproponuj ''dynamiczne'' odpowiedniki obydwu ''statycznych'' semantyk dla | ||
jêzyka funkcyjnego <math>F</math>. | |||
Czyli | Czyli zak³adamy, ¿e widoczno¶æ identyfikatorów, m.in. w ciele funkcji, | ||
jest dynamiczna. | jest dynamiczna. | ||
Oto | Oto przyk³ad programu, który w semantyce statycznej oblicza siê do | ||
warto¶ci <math>12</math>, a w dynamicznej do warto¶ci <math>5</math> | |||
(parametr przekazywany przez | (parametr przekazywany przez warto¶æ): | ||
<math> | <math> | ||
Linia 515: | Linia 517: | ||
</math> | </math> | ||
Rozwa¿ dwa mechanizmy przekazywania parametrów: | |||
* przez | * przez warto¶æ | ||
* przez | * przez nazwê | ||
Ten drugi mechanizm rozumiemy teraz | Ten drugi mechanizm rozumiemy teraz nastêpuj±co. Parametr aktualny nie | ||
jest obliczany w momencie zaaplikowania do niego funkcji, | jest obliczany w momencie zaaplikowania do niego funkcji, | ||
a do | a do cia³a funkcji przekazuje siê wyra¿enie bêd±ce parametrem aktualnym. | ||
W momencie | W momencie odwo³ania do parametru formalnego w ciele funkcji, | ||
wyra¿enie | |||
bêd±ce parametrem aktualnym jest obliczane w bie¿±cym stanie (a nie w | |||
stanie z miejsca | stanie z miejsca wywo³ania funkcji). | ||
Jako | Jako przyk³ad pozwa¿my program: | ||
<math> | <math> | ||
Linia 533: | Linia 535: | ||
</math> | </math> | ||
Przy przekazywaniu przez | Przy przekazywaniu przez warto¶æ, w stanie pustym program siê nie | ||
obliczy, | obliczy, poniewa¿ nie da siê obliczyæ parametru aktualnego <math>x</math>. | ||
Natomiast przy przekazywaniu przez | Natomiast przy przekazywaniu przez nazwê, parametr aktualny bêdzie | ||
obliczany dopiero w momencie | obliczany dopiero w momencie odwo³ania do parametru formalnego <math>z | ||
</math>, czyli w momencie obliczania | </math>, czyli w momencie obliczania warto¶ci wyra¿enia <math>z + z</math>. | ||
W stanie tym zmienna <math>x</math> ma | W stanie tym zmienna <math>x</math> ma ju¿ warto¶æ, a zatem warto¶ci± | ||
ca³ego programu bêdzie 21. | |||
}} |
Wersja z 08:00, 9 sie 2006
Zawarto¶æ
Napiszemy semantykê naturaln± jêzyka wyra¿eñ, rozwa¿ymy strategiê gorliw± (jak na wcze¶niejszych zajêciach, w semantyce ma³ych kroków) i leniw±. Rozwa¿ymy i statyczne i dynamiczne wi±zanie identyfikatorów. Nastêpnie rozszerzymy ten jêzyk o lambda-abstrakcjê i aplikacjê, otrzymuj±c prosty jêzyk funkcyjny.
Ró¿ne semantyki naturalne wyra¿eñ
Ćwiczenie 1 (semantyka gorliwa)
Napisz semantykê du¿ych kroków
dla jêzyka wyra¿eñ, którego semantykê ma³o-krokow±
napisali¶my na jednych z poprzednich æwiczeñ:
Rozwiązanie
Ćwiczenie 2 (semantyka leniwa)
Zmodyfikuj semantykê z poprzedniego zadania, aby uzyskaæ
leniw± ewaluacjê wyra¿eñ, zgodnie z dyrektyw±: nie obliczaj
wyra¿enia o ile jego wynik nie jest potrzebny
(albo: obliczaj warto¶æ wyra¿enia dopiero wtedy, gdy jego wynik jest
naprawdê potrzebny). Spójrzmy na przyk³ad:
Wed³ug semantyki z poprzedniego zadania wyra¿nie to nie ma warto¶ci, bo w deklaracji jest odwo³anie do niezainicjowanej zmiennej. Natomiast w semantyce leniwej wyra¿enie to obliczy siê do warto¶ci , gdy¿ wyra¿enie nie bêdzie wogóle obliczane. Bêdzie tak dlatego, ¿e w wyra¿eniu nie ma odwo³añ do zmiennej .
Rozwiązanie
Ćwiczenie 3 (semantyka dynamiczna)
Rozwa¿my teraz zupe³nie inny mechanizm wi±zania identyfikatorów,
zwany wi±zaniem dynamicznym.
Dla odró¿nienia, dotychczasowy sposób wi±zania (widoczno¶ci)
identyfikatorów bêdziemy nazywaæ wi±zaniem statycznym.
Oto przyk³adowe wyra¿enie:
które nie ma warto¶ci w pustym stanie pocz±tkowym, wed³ug semantyk z poprzednich zadañ, poniewa¿ odwo³anie do zmiennej w deklaracji jest niepoprawne. Tak samo jest nawet w semantyce leniwej, gdy¿ warto¶æ zmiennej bêdzie w koñcu policzona, i bêdzie wymaga³a odwo³ania do w stanie pustym.
Natomiast wyobra¿my sobie, ¿e zmieniamy semantykê leniw± nastêpuj±co: odwo³anie do zmiennej podczas obliczania warto¶ci bêdzie odnosi³o siê nie do stanu w momencie deklaracji , ale do stanu w momencie odwo³ania do . Jest to do¶æ rewolucyjna zmiana, zapewne sprzeczna z intuicjami programisty (statyczne regu³y widoczno¶ci zamieniamy na dynamiczne). W szczególno¶ci powy¿sze wyra¿enie policzy siê w semantyce dynamicznej do warto¶ci 11, poniewa¿ stan w momencie odwo³ania do zmiennej przypisuje zmiennej warto¶æ 10 !
Napisz semantykê naturaln± dla wi±zania dynamicznego.
Rozwiązanie
Prosty jêzyk funkcyjny
Ćwiczenie 4 (przekazywanie parametru przez warto¶æ)
Rozwa¿my prosty jêzyk funkcyjny rozszerzaj±cy
jêzyk wyra¿eñ z poprzednich zadañ nastêpuj±co:
Lambda-abstrakcja reprezentuje anonimow± (nienazwan±) funkcjê jednoargumentow±, natomiast wyra¿enie to aplikacja do (wyra¿enie powinno zatem obliczaæ siê do funkcji). Np.
Przyjmijmy statyczn± widoczno¶æ identyfikatorów. Mo¿liwe s± ró¿ne mechanizmy przekazywania parametrów. Na razie wybierzmy mechanizm przekazywania przez warto¶æ, zapewne doskonale znany Czytelnikowi: wyra¿enie bêd±ce parametrem aktualnym jest obliczane przed wywo³aniem funkcji, czyli w stanie, w którym jeste¶my z momencie wywo³ania funkcji.
Zaproponuj semantykê naturaln± dla tego jêzyka dla obydwu mechanizmów przekazywania parametrów.
Rozwiązanie
Ćwiczenie 5 (przekazywanie parametru przez nazwê)
Zaproponuj leniw± semantykê jêzyka z mechnizmem
przekazywanie parametru przez nazwê.
Mechanizm ten stanowi leniwy odpowiednik przekazywania przez warto¶æ:
nie obliczamy wyra¿enia bêd±cego parametrem aktualnym, a zamiast
jego warto¶ci przekazujemy do funkcji to wyra¿enie wraz ze
stanem z miejsca wywo³ania funkcji.
To ten stan bedzie brany pod uwagê, gdy obliczana bêdzie
warto¶æ parametru, tzn. przy odwo³aniu w ciele funkcji do
parametru formalnego. Oto przyk³ad programu:
który w stanie pustym (wszystkie zmienne nieokre¶lone) nie ma warto¶ci przy przekazywaniu parametru przez warto¶æ (bo odwo³anie do zmiennej jest niepoprawne) a oblicza siê do warto¶ci je¶li wybierzemy mechanizm przekazywania przez nazwê.
Rozwiązanie
Zadania domowe
Ćwiczenie 1
Podaj przyk³ad wyra¿enia takiego, które:
- ma warto¶æ w semantyce statycznej i dynamicznej, ale w ka¿dej inn±
- ma warto¶æ w semantyce leniwej a nie ma w dynamicznej
- ma warto¶æ w semantyce dynamicznej a nie ma w leniwej.
Ćwiczenie 2
W semantyce leniwej wyra¿eñ, je¶li jest wiele odwo³añ do jakiej¶ zmiennej, to obliczenie warto¶ci tej zmiennej nast±pi za ka¿dym razem od nowa. Zmodyfikuj tê semantykê tak, aby warto¶æ ta by³a obliczana co najwy¿ej raz. Zatem po pierwszym odwo³aniu do zmiennej, jej obliczona warto¶æ powinna zostaæ umieszczona w stanie, zastêpuj±c parê (wyra¿enie, stan).
Ćwiczenie 3
Zaproponuj dynamiczne odpowiedniki obydwu statycznych semantyk dla jêzyka funkcyjnego . Czyli zak³adamy, ¿e widoczno¶æ identyfikatorów, m.in. w ciele funkcji, jest dynamiczna. Oto przyk³ad programu, który w semantyce statycznej oblicza siê do warto¶ci , a w dynamicznej do warto¶ci (parametr przekazywany przez warto¶æ):
Rozwa¿ dwa mechanizmy przekazywania parametrów:
- przez warto¶æ
- przez nazwê
Ten drugi mechanizm rozumiemy teraz nastêpuj±co. Parametr aktualny nie jest obliczany w momencie zaaplikowania do niego funkcji, a do cia³a funkcji przekazuje siê wyra¿enie bêd±ce parametrem aktualnym. W momencie odwo³ania do parametru formalnego w ciele funkcji, wyra¿enie bêd±ce parametrem aktualnym jest obliczane w bie¿±cym stanie (a nie w stanie z miejsca wywo³ania funkcji). Jako przyk³ad pozwa¿my program:
Przy przekazywaniu przez warto¶æ, w stanie pustym program siê nie obliczy, poniewa¿ nie da siê obliczyæ parametru aktualnego . Natomiast przy przekazywaniu przez nazwê, parametr aktualny bêdzie obliczany dopiero w momencie odwo³ania do parametru formalnego , czyli w momencie obliczania warto¶ci wyra¿enia . W stanie tym zmienna ma ju¿ warto¶æ, a zatem warto¶ci± ca³ego programu bêdzie 21.