300 likes | 451 Views
Języki i środowiska programowania systemów rozproszonych. Wykład 10 Rozszerzenie języków zapytań o konstrukcje imperatywne. Wykładowca : Tomasz Kowalski Wykłady przygotowane na podstawie materiałów prof. Kazimierza Subiety. Zapytania jako wyrażenia języka programowania.
E N D
Języki i środowiska programowania systemów rozproszonych Wykład 10 Rozszerzenie języków zapytań o konstrukcje imperatywne Wykładowca: Tomasz Kowalski Wykłady przygotowane na podstawie materiałów prof. Kazimierza Subiety
Zapytania jako wyrażenia języka programowania • W SBA zapytania pełnią rolę wyrażeń języka programowania. • Zapytania będą również stosowane do nietrwałych danych. • Inaczej mówiąc przyjęliśmy, że w naszym (hipotetycznym) języku programowania nie będzie innych wyrażeń niż zapytania. • To założenie jest rewolucją w odniesieniu do języków zapytań. • W SQL zapytania zagnieżdżone w język programowania mogły odwoływać się do zmiennych języka programowania poprzez specjalną składnię. • Podział na wyrażenia i zapytania przyjmują języki czwartej generacji (4GL). • PL/SQL system Oracle, pierwszy komercyjny język programowania w pełni zintegrowany z językiem SQL, również wprowadza podział na wyrażenia i zapytania. • Powodem są ograniczenia i narzuty składniowe języka SQL, w którym nie da się bezpośrednio zapisać są tak prostych wyrażeń jak 2+2, sin(x), itd. • Jest jednak oczywiste, że wyrażenia i zapytania muszą mieć niepuste przecięcie, co stawia pod znakiem zapytania ten podział.
Referencje w wynikach zapytań • Okolicznością większości języków zapytań, która ogranicza ich rolę jako wyrażeń, jest to, że zapytanie może zwrócić wartość, ale nie może zwrócić referencji do pewnej danej zapamiętanej w składzie. • Uniemożliwia to wykorzystanie zapytań jako składowych zdań imperatywnych, takich jak podstawienie (update w SQL) lub usuwanie (delete w SQL). • Oficjalnie, SQL również nie zwraca referencji, ale zrealizowanie w nim wymienionych zdań imperatywnych świadczy o tym, że praktyka (na szczęście) rozminęła się z przyjętą oficjalnie teorią. • W SBQL ten problem nie występuje.
Jak to zostało zrobione w systemie Loqis? • Loqis jest prawdopodobnie pierwszym w historii systemem, w którym zrealizowano pełny język programowania oparty na języku SBQL. • Loqis nie wprowadza wyrażeń innych niż zapytania. • Język programowania systemu Loqis posiada zestaw cech, których pełna kombinacja nie występuje w innym języku programowania: • Pełna ortogonalna trwałość, czyli brak jakichkolwiek różnic syntaktycznych i semantycznych w dostępie i operacjach na nietrwałych i trwałych danych. • Pełny relatywizm obiektów w powiązaniu z relatywizmem wyrażeń języka. • Identyczne mechanizmy zakresu i wiązania dla obiektów indywidualnych i dla kolekcji. Brak podziału na zapytania i wyrażenia. Dowolne wyrażenie jest także zapytaniem. Wszelkie operatory występujące tradycyjnie w wyrażeniach mogą występować także w zapytaniach. • Zapytania mogą zwracać zarówno wartości (dowolnie złożone) jak i referencje do obiektów. • Wyniki zapytań w SBQL mogą być specyficznymi strukturami zbudowanymi z wartości, referencji i nazw.
Zastosowania zapytań w jęz. programowania • Zapytania, jako wyrażenia języka programowania, będą używane we wszystkich kontekstach w których używane są wyrażenia, w szczególności w następujących: • Jako składowa zdań imperatywnych, np. instrukcji podstawienia, usuwania, tworzenia i wstawiania. • Jako parametry procedur, funkcji lub metod, przy zachowaniu klasycznych metod przekazywania parametrów znanych jako wołanie przez wartość (call-by-value) oraz wołanie przez referencję (call-by-reference). • Jako składnik zdania return określającego wynik procedury lub metody funkcyjnej. • Jako składnik iteratora znanego jako „for each ... do ...”, określający ilość pętli iteratora oraz element przetwarzany w każdym jego cyklu.
Czy taki język nie jest utopią? Jakie zagrożenia można wiązać z realizacją języka programowania o podanych własnościach? • Niska wydajność. Ale: • Wiele metod optymalizacyjnych wiązanych z modelem relacyjnym ma bezpośrednie odpowiedniki dla modeli obiektowych. Np. indeksy. • Dla SBQL zostały odkryte nieznane wcześniej bardzo mocne metody optymalizacyjne oparte na przepisywaniu. • Trudności z wypromowaniem nowego języka programowania. Ale: • Java stała się szybko popularna, mimo że nie występują w niej cechy nieznane w poprzednich językach. (Jest nową kombinacją popularnych cech.) • PHP w ciągu dwóch lat zdobył miliony zwolenników. • Wiele rynkowych systemów jest wyposażana w języki o bardzo specyficznych nazwach i rozwiązaniach. Użytkownikom to nie przeszkadza. • Świat badawczo-rozwojowy nie może zastopować badań i rozwoju z powodu potencjalnych trudności z powszechnym wdrożeniem.
Konstrukcje deklaratywne i imperatywne • Założeniem języków zapytań jest deklaratywność, czyli wyrażanie bezpośrednio celu wyszukiwania. • Deklaratywność jest wiązana z programowaniem w logice, np. językami Prolog lub Datalog. Zwolennicy tego podejścia twierdzą niekiedy, że tylko wyrażenia logiki matematycznej (i pochodne) są deklaratywne. • Są to próby zbudowania fałszywego stereotypu. Pseudo-naukowe bzdury. • Deklaratywność wynika z psychologii, odczuć użytkownika języka, a nie z jakichkolwiek tworów formalnych. • Deklaratywność nie jest celem samym w sobie - ma o tyle znaczenie, o ile skraca czas tworzenia programu, czyni go bardziej zrozumiałym, oraz zapewnia łatwiejszą i mniej kosztowną jego pielęgnację. • Kluczem do deklaratywności jest uzyskanie jak najprostszego odwzorowania pojęciowego pomiędzy rzeczywistym problemem w dziedzinie przedmiotowej, a zapisem bądź rozwiązaniem tego problemu w środowisku komputerowym.
Konstrukcje deklaratywne a zmiany stanu • Konstrukcje deklaratywne nie mogą (nie powinny) zmieniać stanu. • Stan jest pojęciem związanym z czasem i następstwem czynności. Zmiany stanu wymagają wprowadzenia konstrukcji imperatywnych. • Twórcy koncepcji opartych na programowaniu w logice starają się retuszować ten oczywisty fakt poprzez różnorodne konstrukcje. • Np. w systemie LDL zastosowano "mimikrę syntaktyczną" w postaci symbolu -, który przypomina negację, ale w istocie jest konstrukcją imperatywną, której semantyką jest usunięcie pewnej danej. • Obecność tego rodzaju sztuczek stawia pytanie, czy w misji zbudowania fałszywego stereotypu „programowania deklaracyjnego” niektórzy naukowcy nie posuwają się zbyt daleko, poza granicę etyki naukowej, która zabrania oszukiwania czytelników, użytkowników (i samych siebie). • Z reguły, zmiany stanu są przemycane w tego rodzaju koncepcjach i językach poprzez różnorodne efekty uboczne. • Te "efekty uboczne" podkopują formalną podstawę programowania w logice; powodują, że tysiące twierdzeń i wniosków udowodnionych przez armię akademickich "teoretyków" można a priori skierować do składu śmieci.
SBQL a konstrukcje imperatywne • Przy rozszerzeniach SBQL będziemy starali się trzymać czystości rozdzielenia tej części języka, która nie może zmienić stanu obiektów (czyli deklaratywnych zapytań), oraz części, która będzie zajmować się zmianami stanu (czyli części imperatywnej). • Efekty uboczne w zapytaniach będziemy uważać za niewskazane. • Poprzez efekty uboczne wyrażenia stają się mniej czytelne, błędogenne oraz bardziej kłopotliwe podczas zmian oprogramowania; • Efekty uboczne mogą zakłócić lub uniemożliwić optymalizację zapytań. • Nie możemy też zabronić użycia efektów ubocznych w zapytaniach. • Programista może wewnątrz zapytania wywołać funkcję lub metodę. • Nie będziemy dzielić funkcji i metod w zależności od posiadania efektów ubocznych. Wprowadziłoby to zbytnią komplikację do języka i jego użycia. • Efekty uboczne w zapytaniach powinny być stosowane w sytuacji pewności, że nie zakłóci to optymalizacji i nie doprowadzi do złego wyniku.
Zasada korespondencji correspondence principle • Podstawowy drogowskaz przy konstruowaniu języka programowania. • Zasada korespondencji mówi, że wraz z wprowadzeniem do języka pewnej cechy X należy precyzyjnie określić inne cechy języka w taki sposób, aby cecha X współdziałała z już istniejącymi konstrukcjami, została wtopiona w istniejące lub zmodyfikowane mechanizmy nazywania, typowania, zakresu i wiązania, oraz miała zapewnioną uniwersalną obsługę. • Przykładowo, jeżeli cecha X jest dynamiczną tablicą, to odpowiednimi pytaniami są: czy może ona być składową zapisu (struktury, obiektu), czy może być parametrem procedury, czy może być zwrócona przez procedurę funkcyjną, jakie środki będą przewidziane do typizacji, wyszukiwania, aktualizacji, usuwania, dostawiania elementów; itd. • Oddolny rozwój niektórych języków (np. SQL) jest przyczyną wielu przypadków łamania zasady korespondencji, co objawia się m.in. tym, że nowo dodawane cechy nie są gładko połączone ze starymi cechami.
Zasada korespondencji w środowisku wytwórczym • Zasada korespondencji powinna być rozszerzona dalej, poza samą definicję języka. • Jeżeli wprowadzamy cechę X, to ważne stają się odpowiedzi na pytania: • Czy istnieje dostatecznie jasna pragmatyka cechy X, tj. sposób przełożenia konkretnej potrzeby w dziedzinie przedmiotowej na zastosowanie cechy X? • Czy cecha X jest uwzględniona w metodyce projektowania aplikacji i/lub metodyce projektowania baz danych? • Jeżeli nie, to cecha X stanie się cechą uboczną. • Czy cecha X nie jest redundantna? • Czy i jak cecha X będzie osiągalna z zewnętrznych interfejsów, nie bazujących na definiowanym przez nas języku, np. ODBC lub JDBC? • Jak cecha X została udokumentowana i objaśniona na przykładach? • Dokumentacja i przykłady są często lakoniczne, zbyt matematyczne lub infantylne. • Czy cecha X jest błędogenna lub niebezpieczna dla powszechnego programisty, czy nie prowadzi do raf semantycznych? • Jakie środki dydaktyczne będą zastosowane celem objaśnienia i zareklamowania użycia cechy X?
Elementarne imperatywne konstrukcje językowe • Celem następnych slajdów jest omówienie tych konstrukcji imperatywnych, które mogą mieć znaczenie przy budowie języka programowania opartego o język zapytań. • Ponieważ konstrukcje imperatywne istnieją w tysiącach różnorodnych języków programowania, wynajdywanie nowych rozwiązań jest niepotrzebne. • Będziemy raczej oceniać popularne i powszechnie używane konstrukcje, takie jak if...then...else..., while...do..., itd., celem ustalenia ich przydatności i ewentualnych modyfikacji w przypadku języka programowania opartego na zapytaniach.
Operator tworzenia obiektu • Może to być deklarowanie obiektu, czyli utworzeniem obiektu w momencie inicjacji pewnej abstrakcji programistycznej (np. metody). • Może to być dynamiczne utworzenie obiektu na polecenie wydane explicite przez programistę - operator musi być dodatkowo parametryzowany miejscem składu i statusem trwałości. • Operator powinien być makroskopowy. • Operator powinien dawać możliwość utworzenia nowej danej elementarnej oraz nowej danej pointerowej wewnątrz określonego obiektu. • Operator powinien dawać możliwość utworzenia nowego modułu, klasy, metody, perspektywy, procedury, ograniczenia, trygera, itd. • Generalnie, dla dowolnego elementu składu obiektów powinna istnieć odmiana tego operatora pozwalająca na utworzenie tego elementu w określonym środowisku.
Referencje do środowisk na stosie ENVS • Jeżeli utworzony został nowy obiekt, to istotne jest uaktualnienie stosu ENVS poprzez wstawienie tam – w razie potrzeby – odpowiedniego bindera do nowego obiektu. • Dla każdego środowiska reprezentowanego przez sekcję stosu ENVS pamiętana jest także referencja (lub referencje) do środowiska (środowisk) składu obiektów, które były podstawą skonstruowania danej sekcji stosu. • Następnie po utworzeniu obiektu porównuje się referencję do środowiska, wewnątrz którego został utworzony nowy obiekt, z referencjami do wszystkich środowisk reprezentowanych na stosie ENVS. • Jeżeli dla danej sekcji referencje są identyczne, wówczas do tej sekcji wstawia się odpowiedni binder, patrz następny slajd. • Przykładowo, jeżeli tworzymy lub wstawiamy nowy obiekt Stan z referencją i765 do wnętrza obiektu Pracownik z identyfikatorem i9, wówczas przeglądamy kolumnę „Referencje do środowisk” stosu ENVS, następnie znajdując tam również referencję i9dostawiamy do tej sekcji w kolumnie „Bindery” binder Stan(i765 ). Czynność tę wykonujemy dla każdej sekcji, która zawiera referencję do środowiska i9.
ENVS z referencjami do środowisk • Przy optymalizowanej wersji stosu ENVS w istocie pamiętana jest tylko pierwsza kolumna, jeżeli zawiera referencje do środowisk, i druga kolumna w pozostałych przypadkach. To oznacza, że operacje, tworzenia, wstawiania lub usuwania obiektu nie wymagają w większości jakichkolwiek działań na stosie ENVS. Referencje do środowisk Bindery - i127, i478 ......... i9 ......... ibd ......... Prac(i1) X(i127) Y(i128) N(5) I("Maria") ......... Nazwisko(i10) Zar(i11) Adres(i12) PracujeW(i16) ......... Prac(i1) Prac(i5) Prac(i9) Dział(i17) Dział(i22) ......... Środowsko pointera Referencje do lokalnych środowisk Referencja do obiektu Referencja do środowiska bazy danych
Instrukcja create • Najprostszą formą syntaktyczną instrukcji tworzenia obiektu jest: zapytanie ::= instrukcja_create instrukcja ::= instrukcja_create instrukcja_create ::= create [gdzie] zapytanie; gdzie ::= local | temporary | permanent • Zapytanie będące argumentem instrukcji create może zwrócić bag. • Zostanie wówczas utworzonych tyle obiektów, ile elementów ma ten bag (w szczególności ani jednego, jeżeli bag jest pusty). • Wynikiem instrukcji jest referencja (bag referencji) do utworzonych obiektów. • Nazwy tworzonych obiektów oraz ich pod-obiektów są określone przez odpowiednie bindery będące wynikiem tego zapytania. • Dla wszystkich referencji zwróconych przez to zapytanie jest wykonywana automatycznie dereferencja. • Miejsce tworzenia obiektu jest ustalone przez kwalifikator gdzie.
Referencje w instrukcji create • Poprzez dodanie nowej prostej konstrukcji do SBQL można również w ten sposób tworzyć obiekty pointerowe. Załóżmy składnię zapytanie ::=ref zapytanie • i przyjmijmy, że w każdej sytuacji (nie tylko związanej z create) refq zwraca referencję r (lub wiele referencji) zwróconą przez zapytanie q, która nie podlega dereferencji. • Technicznie, referencja r jest opatrzona specjalną flagą, która zabrania użycia dereferencji i zabrania automatycznego wywołania procedury, funkcji lub metody poprzez referencję r z tą flagą. • Jeżeli instrukcja create napotka referencję z taka flagą, wówczas tworzy obiekt pointerowy.
Przykłady tworzenia obiektów • Instrukcja create tworzy w trwałym składzie obiekt pracownika Kowalskiego, po zatrudnieniu go w dziale marketingu. create permanent ( 2453456 asNrP, ”Kowalski” asNazwisko, ”analityk” asStan, 2350 asZar, (refDziałwhereNazwa = “Marketing”) asPracujeW ) asPrac • Instrukcja create tworzy lokalnie od zera do dowolnej liczby obiektów pointerowych z nazwą analityk, prowadzących do obiektów Prac. Następnie instrukcja for each każdemu w ten sposób wyselekcjonowanemu analitykowi podnosi zarobek o 100. create (refPracwhereStan = ”analityk”) asanalityk; for eachanalityk.PracdoZar := Zar +100;
Przypisywanie obiektów do klas • Kolejnym zagadnieniem, które należy rozstrzygnąć przy tworzeniu nowego obiektu jest podłączenie go do klasy. • Można to zrobić poprzez dodatkową składnię związaną z instrukcją create, np.: instrukcja_create ::=create [gdzie] zapytanie as member of nazwaKlasy • Przyjmujemy tu, że wszystkie klasy są bytami pierwszej kategorii dostępnymi do wiązania w środowisku, w którym wydana została ta instrukcja. • Skutkiem jest wytworzenie specyficznego związku pointerowego pomiędzy utworzonym obiektem a jego bezpośrednią klasą, który jest używany przez procedurę eval dla załadowania binderów do wnętrza klasy wraz z binderami do wnętrza obiektu, tak jak to było objaśnione dla modeli AS1 i AS2.
Operator podstawienia (update w SQL) • Operator podstawienia możemy zrealizować w klasycznym wariancie instrukcja ::= zapytanie := zapytanie • Podstawienie ma postać l-value := r-value , gdzie l-value (lewa wartość) jest wyrażeniem zwracającym referencję, zaś r-value (prawa wartość) jest wyrażeniem zwracającym wartość. • Operatora dokonuje zamiany bieżącej wartości obiektu posiadającego identyfikator zwrócony przez l-value na wartość określoną przez r-value. • Operator podstawienia w wersji języka zapytań prowadzi do konieczności ustalenia następujących aspektów: • Czy ma być makroskopowy, tj. czy l-value i r-value mogą być określane przez zapytania zwracające bagi lub sekwencje? • Czy możliwe będzie podstawienie na obiekt złożony? • Czy możliwe będzie podstawienie na obiekt pointerowy? • Odpowiedzi na te pytania muszą być pozytywne, inaczej złamana będzie zasada korespondencji.
Podstawienie makroskopowe • Przyjęcie składni q1 := q2 jest nieakceptowalne w sytuacji, gdy q1 i q2 zwracają bagi, ponieważ nie będzie wiadomo, która wartość ma być podstawiona na którą referencję. • Taka składnia jest również nieakceptowalna w sytuacji, gdy q1 i q2 zwracają sekwencje, gdyż zmusza to programistę do starannej kontroli, czy rozmiar sekwencji i wzajemne dopasowanie poszczególnych ich elementów są w pełni spójne. • Pozostają dwa rozwiązania: • Nie dopuszczamy podstawienia makroskopowego: w konstrukcji q1 := q2 zapytanie q1 musi zwrócić dokładnie jedną referencję, zaś zapytanie q2 musi zwrócić dokładnie jedną wartość. • Makroskopowość podstawienia będzie osiągnięta poprzez konstrukcję for each. • Wprowadzamy nowy operator update z parametrem będącym pojedynczym zapytaniem. Zapytanie to zwraca bag struktur dwu-elementowych, gdzie pierwszy element każdej struktury jest traktowany jako l-value, zaś drugi element jest traktowany jako r-value. • Rozwiązanie to zostało zaimplementowane w systemie Loqis.
Przykłady podstawienia • Podwyższ o 100 zarobek wszystkim programistom: for eachPracwhereStan = ”programista” doZar := Zar + 100; • Alternatywnie: update (PracwhereStan = ”programista”) . (Zar, Zar + 100); • Podwyższ o 100 zarobek wszystkim programistom i zmień im stanowisko na ”inżynier”: for eachPracwhereStan = ”programista” do { Zar := Zar + 100; Stan := ”inżynier”; }; • Forma alternatywna wymaga wprowadzenia bagów z typologicznie niekompatybilnymi strukturami: update (PracwhereStan = ”programista”) . bag((Zar, Zar + 100), (Stan, ”inżynier”)); • Rozwiązanie to może być nieakceptowalne od strony mocnej kontroli typów.
Podstawienie na daną pointerową • Podstawienie na daną pointerową można zdefiniować przy pomocy wprowadzonego już kwalifikatora ref, który informuje, że chodzi o referencję. • Przenieś wszystkich programistów do działu Nowaka: for eachPracwhereStan = ”programista” do PracujeW := refDziałwhere (Szef.Prac.Nazwisko) = ”Nowak”; • Alternatywnie: update (PracwhereStan = ”programista”) . (PracujeW,ref (Działwhere (Szef.Prac.Nazwisko) = ”Nowak”));
Podstawienie na obiekt złożony • Podstawienie na obiekt złożony przypomina instrukcję create. • Identyfikator obiektu, na który się podstawia, nie ulega zmianie. • Wszystkie pod-obiekty tego obiektu są usuwane, następnie tworzone są nowe pod-obiekty na podstawie prawej strony podstawienia. • Powinna ona zawierać strukturę z binderami; bindery wyznaczają nazwy tworzonych pod-obiektów. • Wstaw nowe dane Nowaka: (PracwhereNazwisko = ”Nowak”) := ( 4536 asNrP, ”Nowak” asNazwisko, ”analityk” asStan,2500 asZar, ( ”Radom” asMiasto, ”Nowa” asUlica, 76 asNrDomu) asAdres, ( refDziałwhereNazwa = „Magazyn”) asPracujeW );
Podstawienie zawartości innego obiektu • Drobnym problemem technicznym jest definicja dereferencji dla złożonego obiektu. Struktura binderów odwzorowująca obiekt 1:1 jest pomysłem na taką dereferencję. • Przykładowo: • Na obiekt pracownika Doe podstaw dane pracownika Poe: (PracwhereNazwisko=”Doe”) := (PracwhereNazwisko=”Poe”) Obiekt: < i9 , Prac , { < i10, Nazwisko, ”Poe” >, < i11, Zar, 900 >, < i12, Adres, { < i13, Miasto, ”Radom” >, < i14, Ulica, ”Wolska” >, < i15, NrDomu, 12 > } >, < i16, PracujeW, i22 > } > Dereferencjaderef(i9): struct{ Nazwisko( ”Poe” ), Zar( 900 ), Adres( struct{ Miasto(”Radom”), Ulica(”Wolska”), NrDomu(12)}, PracujeW ( ref i22 ) }
Operator wstawiania • Operator wstawiania obiektu powinien umożliwiać wstawianie makroskopowe, w stylu klauzuli insert języka SQL. • Ma wstawić pewien obiekt jako podobiekt innego obiektu. Wybrany obiekt jest przesuwany z dotychczasowego środowiska do określonego środowiska. • Powinien on działać na wszystkich typach obiektów, włączając obiekty złożone, klasy, metody, perspektywy, itd. • Np. jeżeli dowolny obiekt analityka nie ma atrybutu Zar, to wstaw mu do środka taką daną z wartością 1000. for each (PracwhereStan = ”analityk” andcount(Zar) = 0) aspdo { insert( p, create 1000 asZar ); } • Dla wszystkich obiektów pracowników wstaw pod-obiekt zarabiał z konkatenacją aktualnej daty i aktualnego zarobku danego pracownika. insert (Pracas p) . ( p, create ((string)Date º (string)(p.Zar)) aszarabiał);
Operator usuwania • Operator usuwania powinien umożliwiać usuwanie makroskopowe, w stylu klauzuli delete języka SQL. • Dotyczy obiektów tworzonych (nie deklarowanych) przez programistę i oznacza usunięcie obiektu z określonego środowiska. • Operator usuwania powinien dotyczyć wszystkich rodzajów obiektów, w tym obiektów atomowych, pointerowych, złożonych., klas, metod, perspektyw, itd. • Niektórzy lansują pogląd, że operator usuwania nie powinien być dostępny programiście, gdyż może prowadzić do tzw. zwisających pointerów. • Programista usuwa pointery do obiektu, natomiast usunięcie samego obiektu załatwia automatyczny odśmiecacz (garbage collector). • Ten pogląd jest powierzchowny, wynikający z niezrozumienia problemu. • Pozostawienie obiektu, który już nie powinien istnieć, jest tak samo błędogenne jak zwisający pointer. Należy usuwać obiekty z automatycznym usunięciem/wyzerowaniem prowadzących do nich pointerów.
Operatory warunkowe i przełączania • Operator warunkowy: if <warunek> then <program1> else <program2> if <warunek> then <program> • Wariant dla wyrażeń:if <warunek> then <zapytanie1> else <zapytanie2> • Operator przełączania: posiada wiele wariantów, np. case <wyrażenie> do <etykieta 1>: <program 1>, <etykieta 2>: <program 2>, ... <etykieta n>: <program n> else <program n+1> • Semantycznie, obliczane jest <wyrażenie>; jeżeli wyrażenie zwróci wartość <etykieta i> wówczas wykonywany jest <program i>. • Jeżeli <wyrażenie> nie zwróciło wartości równej jakiejkolwiek etykiecie, wówczas wykonywany jest <program n+1>. • Fraza else jest zwykle opcyjna.
Operatory pętli • while<warunek>do<program> • Operator powtarza wyliczenie wyrażenia <warunek> i wykonanie bloku <program> aż do momentu, kiedy <warunek> będzie nieprawdziwy. Jeżeli <warunek> jest na samym początku nieprawdziwy, wówczas <program> nie jest wykonywany ani razu. • repeat <program> until <warunek> • Najpierw następuje wykonanie bloku <program>, następnie wyliczenie wyrażenia <warunek>; jeżeli jest prawdziwy, to sterowanie jest przekazywane dalej, w przeciwnym przypadku powtarzane jest wykonanie bloku <program>, z ponownym wyliczeniem wyrażenia <warunek>. • Modyfikacja tych operatorów polega na wprowadzeniu specjalnej instrukcji break, której wykonanie wewnątrz <program> powoduje przekazanie sterowania do instrukcji znajdującego się za tą konstrukcją. • loop <program> • przerwanie pętli wymaga użycia instrukcji break.
Operator for each • Składnia: for each <zapytanie> do <program> • Semantyka: przyjmujemy zasadę operatorów nie-algebraicznych • Dla każdego e zwróconego przez <zapytanie>, ENVS jest podwyższany o nested(e). W modelach AS1, AS2 jeżeli e zawiera referencje do obiektów, to na ENVST są wkładane sekcje z binderami do wnętrza odpowiednich klas. • Następnie wykonywany jest <program>. • Po zakończeniu wykonania <program> ENVS wraca do poprzedniego stanu. • Cykl ten jest powtarzany dla wszystkich elementów zwróconych przez <zapytanie>. • Tak jak w operatorach nie-algebraicznych, "zmienna iteracyjna" jest definiowana przez operator as i nie musi wystąpić. • Przykłady: • for eachPracwhereStan = "asystent" doZar := Zar + 100; • for each (PracwhereStan = "asystent") aspdo { p.Zar := p.Zar + 100; p.Stan := "starszy asystent"};