© K.Subieta. Obiektowe języki zapytań 13, Folia 1 czerwiec 2004 Obiektowe języki zapytań Wykładowca: Kazimierz Subieta Polsko-Japońska Wyższa Szkoła Technik Komputerowych, Warszawa Instytut Podstaw Informatyki PAN, Warszawa Wykład 13: Rozszerzenie języków zapytań o konstrukcje imperatywne
© K.Subieta. Obiektowe języki zapytań 13, Folia 2 czerwiec 2004 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ł.
© K.Subieta. Obiektowe języki zapytań 13, Folia 3 czerwiec 2004 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.
© K.Subieta. Obiektowe języki zapytań 13, Folia 4 czerwiec 2004 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.
© K.Subieta. Obiektowe języki zapytań 13, Folia 5 czerwiec 2004 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.
© K.Subieta. Obiektowe języki zapytań 13, Folia 6 czerwiec 2004 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.
© K.Subieta. Obiektowe języki zapytań 13, Folia 7 czerwiec 2004 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.
© K.Subieta. Obiektowe języki zapytań 13, Folia 8 czerwiec 2004 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.
© K.Subieta. Obiektowe języki zapytań 13, Folia 9 czerwiec 2004 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.
© K.Subieta. Obiektowe języki zapytań 13, Folia 10 czerwiec 2004 Zasada korespondencji 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. correspondence principle
© K.Subieta. Obiektowe języki zapytań 13, Folia 11 czerwiec 2004 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?
© K.Subieta. Obiektowe języki zapytań 13, Folia 12 czerwiec 2004 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.
© K.Subieta. Obiektowe języki zapytań 13, Folia 13 czerwiec 2004 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.
© K.Subieta. Obiektowe języki zapytań 13, Folia 14 czerwiec 2004 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ą i 765 do wnętrza obiektu Pracownik z identyfikatorem i 9, wówczas przeglądamy kolumnę Referencje do środowisk stosu ENVS, następnie znajdując tam również referencję i 9 dostawiamy do tej sekcji w kolumnie Bindery binder Stan(i 765 ). Czynność tę wykonujemy dla każdej sekcji, która zawiera referencję do środowiska i 9.
© K.Subieta. Obiektowe języki zapytań 13, Folia 15 czerwiec 2004 ENVS z referencjami do środowisk Prac(i 1 ) X(i 127 ) Y(i 128 ) N(5) I("Maria") Nazwisko(i 10 ) Zar(i 11 ) Adres(i 12 ) PracujeW(i 16 ) Prac(i 1 ) Prac(i 5 ) Prac(i 9 ) Dział(i 17 ) Dział(i 22 ) Środowsko pointera Referencje do lokalnych środowisk Referencja do obiektu Referencja do środowiska bazy danych - i 127, i i i bd Referencje do środowisk Bindery 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.
© K.Subieta. Obiektowe języki zapytań 13, Folia 16 czerwiec 2004 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.
© K.Subieta. Obiektowe języki zapytań 13, Folia 17 czerwiec 2004 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) ref q 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.
© K.Subieta. Obiektowe języki zapytań 13, Folia 18 czerwiec 2004 Przykłady tworzenia obiektów Instrukcja create tworzy w trwałym składzie obiekt pracownika Kowalskiego, po zatrudnieniu go w dziale marketingu. create permanent ( as NrP, Kowalski as Nazwisko, analityk as Stan, 2350 as Zar, (ref Dział where Nazwa = Marketing) as PracujeW ) as Prac 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 (ref Prac where Stan = analityk) as analityk; for each analityk.Prac do Zar := Zar +100;
© K.Subieta. Obiektowe języki zapytań 13, Folia 19 czerwiec 2004 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 M1 i M2.
© K.Subieta. Obiektowe języki zapytań 13, Folia 20 czerwiec 2004 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.
© K.Subieta. Obiektowe języki zapytań 13, Folia 21 czerwiec 2004 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.
© K.Subieta. Obiektowe języki zapytań 13, Folia 22 czerwiec 2004 Przykłady podstawienia Podwyższ o 100 zarobek wszystkim programistom: for each Prac where Stan = programista do Zar := Zar + 100; Alternatywnie: update (Prac where Stan = programista). (Zar, Zar + 100); Podwyższ o 100 zarobek wszystkim programistom i zmień im stanowisko na inżynier: for each Prac where Stan = programista do { Zar := Zar + 100; Stan := inżynier; }; Forma alternatywna wymaga wprowadzenia bagów z typologicznie niekompatybilnymi strukturami: update (Prac where Stan = programista). bag((Zar, Zar + 100), (Stan, inżynier)); Rozwiązanie to może być nieakceptowalne od strony mocnej kontroli typów.
© K.Subieta. Obiektowe języki zapytań 13, Folia 23 czerwiec 2004 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 each Prac where Stan = programista do PracujeW := ref Dział where (Szef.Prac.Nazwisko) = Nowak; Alternatywnie: update (Prac where Stan = programista). (PracujeW, ref (Dział where (Szef.Prac.Nazwisko) = Nowak));
© K.Subieta. Obiektowe języki zapytań 13, Folia 24 czerwiec 2004 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: (Prac where Nazwisko = Nowak) := ( 4536 as NrP, Nowak as Nazwisko, analityk as Stan, 2500 as Zar, (Radom as Miasto, Nowa as Ulica, 76 as NrDomu) as Adres, ( ref Dział where Nazwa = Magazyn) as PracujeW );
© K.Subieta. Obiektowe języki zapytań 13, Folia 25 czerwiec 2004 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: (Prac where Nazwisko=Doe) := (Prac where Nazwisko=Poe) Obiekt: < i 9, Prac, {, < i 12, Adres, {, } >, } > Dereferencja deref( i 9 ): struct{ Nazwisko( Poe ), Zar( 900 ), Adres( struct{Miasto(Radom), Ulica(Wolska), NrDomu(12)}, PracujeW ( ref i 22 ) }
© K.Subieta. Obiektowe języki zapytań 13, Folia 26 czerwiec 2004 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ą for each (Prac where Stan = analityk and count(Zar) = 0) as p do { insert ( p, create 1000 as Zar ); } Dla wszystkich obiektów pracowników wstaw pod-obiekt zarabiał z konkatenacją aktualnej daty i aktualnego zarobku danego pracownika. insert (Prac as p). ( p, create ((string)Date º (string)(p.Zar)) as zarabiał);
© K.Subieta. Obiektowe języki zapytań 13, Folia 27 czerwiec 2004 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.
© K.Subieta. Obiektowe języki zapytań 13, Folia 28 czerwiec 2004 Inne operatory elementarne Operator deklaracji stałej lub makrosa. Można go uważać za operator tworzenia obiektu niemodyfikowalnego. Istotą tego operatora jest to, że wszelkie operacje związane z tym operatorem są wykonywane podczas kompilacji. Deklaracja ma np. postać: constant = ; gdzie jest w zasadzie dowolnym tekstem (tzw. makrosem) który zastąpi po kompilacji każde użycie. Operator zmiany nazwy obiektu lub utworzenia nowego aliasu dla obiektu. Dotyczy raczej szczególnych sytuacji i jest możliwy wyłącznie w przypadku gdy nazwy obiektów są pierwszej kategorii programistycznej. Operator zmiany nazwy powinien być makroskopowy. Operatory dotyczące zdarzeń: wygenerowanie zdarzenia, przechwycenie zaistniałego zdarzenia.
© K.Subieta. Obiektowe języki zapytań 13, Folia 29 czerwiec 2004 Operatory warunkowe i przełączania Operator warunkowy: if then else if then Wariant dla wyrażeń: if then else Operator przełączania: posiada wiele wariantów, np. case do :,... : else Semantycznie, obliczane jest ; jeżeli wyrażenie zwróci wartość wówczas wykonywany jest. Jeżeli nie zwróciło wartości równej jakiejkolwiek etykiecie, wówczas wykonywany jest. Fraza else jest zwykle opcyjna.
© K.Subieta. Obiektowe języki zapytań 13, Folia 30 czerwiec 2004 Operatory pętli while do Operator powtarza wyliczenie wyrażenia i wykonanie bloku aż do momentu, kiedy będzie nieprawdziwy. Jeżeli jest na samym początku nieprawdziwy, wówczas nie jest wykonywany ani razu. repeat until Najpierw następuje wykonanie bloku, następnie wyliczenie wyrażenia ; jeżeli jest prawdziwy, to sterowanie jest przekazywane dalej, w przeciwnym przypadku powtarzane jest wykonanie bloku, z ponownym wyliczeniem wyrażenia. Modyfikacja tych operatorów polega na wprowadzeniu specjalnej instrukcji break, której wykonanie wewnątrz powoduje przekazanie sterowania do instrukcji znajdującego się za tą konstrukcją. loop przerwanie pętli wymaga użycia instrukcji break.
© K.Subieta. Obiektowe języki zapytań 13, Folia 31 czerwiec 2004 Operator for each Składnia: for each do Semantyka: przyjmujemy zasadę operatorów nie-algebraicznych Dla każdego e zwróconego przez, ENVS jest podwyższany o nested(e). W modelach M1, M2, M3, 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. Po zakończeniu wykonania ENVS wraca do poprzedniego stanu. Cykl ten jest powtarzany dla wszystkich elementów zwróconych przez. Tak jak w operatorach nie-algebraicznych, "zmienna iteracyjna" jest definiowana przez operator as i nie musi wystąpić. Przykłady: for each Prac where Stan = "asystent" do Zar := Zar + 100; for each (Prac where Stan = "asystent") as p do { p.Zar := p.Zar + 100; p.Stan := "starszy asystent"};
© K.Subieta. Obiektowe języki zapytań 13, Folia 32 czerwiec 2004 Iteratory niższego poziomu Występują w postaci spójnej rodziny operatorów lub metod, niekiedy hermetyzowanej w postaci klasy lub szablonu. Służą do sekwencyjnego przetwarzania elementów kolekcji. Typowym przykładem są kursory znane z języka SQL lub iteratory. Klasyczny zestaw takich operatorów jest następujący (z dokładnością do nazw operatorów): getFirst, getNext, getPrior, wyjątek NoMoreElements Zwykle takie metody zwracają referencję do bieżącego elementu, która dalej jest przetwarzana przy pomocy standardowych metod (nie dotyczy to SQL). Iteratory niższego poziomu można zastąpić konstrukcją for each, ale nie zawsze. Istnieją zadania, których nie można zrealizować przy pomocy for each; klasycznym przykładem jest algorytm zlania (merging) dwóch posortowanych zbiorów w jeden posortowany zbiór. Problem z iteratorami niższego poziomu polega na tym, że wymagają one wprowadzenia pojęcia elementu bieżącego. To prowadzi do trudności z zagnieżdżonym wywoływaniem iteratorów, w szczególności z rekurencją.