wtorek, 4 listopada 2008
Query Language in Java
Domain Specific Language
The basic idea of a domain specific language (DSL) is a computer language that's targeted to a particular kind of problem, rather than a general purpose language that's aimed at any kind of software problem. blog:DSL
Pewnym uszczegółowieniem tej koncepcji jest pomysł aby w języku konkretnego przeznaczenia (np. języku programowania) stworzyć wrażenie innego języka (wspominałem juz o LINQ?). Bardzo ciekawe jak te mainstreamowe języki ewoluują. Ostatnio natknąłem się na querydsl (warto jest to póki co najlepszy projekt z tym pomysłem). Niewątpliwie i tak tutaj najbardziej narozrabiał Microsoft ze swoim rozszerzeniem LINQ, ale projekty próbujące tego samego w JAVA rosną ostatnio jak grzyby po deszczu; a ja mam wrażenie jakby powstał taki lepszy, mocno typowany JDBC - nice.
niedziela, 19 października 2008
Home cooking: metaprogramming a'la Python
Metaprogramowanie to najprościej rzecz ujmując pisanie programów, które piszą programy. Lekki wstęp można znaleźć tutaj wikipedia:Metaprogramming, a całą koncepcję najłatwiej wyjaśnić na przykładzie LISPA, w którym program piszę się bezpośrednio w drzewie składniowym a kod programu jest listą. Zatem przy niewielkiej zmianie w syntaktyce można stworzyć konstrukcje (tutaj: makro), które w momencie uruchomienia generuje inną listę i ją wywołuję jako program.
No dobra, ale po co to wszystko? Okazuje się, że to bardzo potężny mechanizm, a Paul Graham twierdzi, że jego programy w LISP były złożone w około 40% z makr, co pozwalało mu tworzyć web-dwa-zero projekt (który został ostatecznie wykupiony przez Yahoo) znacznie szybciej niż jego ówczesna konkurencja.
No wielkim zaskoczeniem nie będzie, że metaprogramowanie zostało dorzucone również do Pythona, a konstrukcja, która na to pozwala to Metaclasses. Na sam początek:
Metaclasses are deeper magic than 99% of users should ever worry about. If you wonder whether you need them, you don't (the people who actually need them know with certainty that they need them, and don't need an explanation about why). -- Tim Peters
A więc motywacje już mamy (!)
Na początek problem: Stworzyć interpreter zapytań podobnych do tych tutaj sbql:examples. Dodatkowo niech program nie będzie dłuższy niż cztery ekrany. Oczywiście podobieństwo naszych zapytań do zapytań języka SBQL jest mocno naciągane, niemniej jednak przyjrzyjmy się:
class Osoba():
__metaclass__ = pql_memorystore
imie = Attribute(str, "[*..2]")
nazwisko = Attribute(type = str, card = "[1..1]")
wiek = Attribute(int)
def __init__(self, imie, nazwisko):
self.imie = imie
self.nazwisko = nazwisko
w drugiej linijce określamy tylko metaklasę dla naszej, klasy co sprawia, że nasza żmudnie tworzona klasa Osoba po zakończeniu jej definicji staje sie już zupełnie czymś innym. A w naszym przypadku będzie listą. Czyli mamy klasę, która jest jednocześnie listą i dodatkowo każda nowa instancja tej klasy odkłada się do siebie... weird kind of magic
hmmm sprawdźmy:
Możemy zatem tworzyć obiekty:
o1 = Osoba(imie = "Adam", nazwisko = "Janskowski")
o2 = Osoba(imie = "Janek", nazwisko = "Wlodarczyk")
Osoba("Sigmun", "Freud")
Osoba(imie = "Adam", nazwisko = "Malysz")
Osoba("Tolek", "Skoczylas")
i wykonywać na nich coś w rodzaju zapytań, które operują na instancjach własnych klas:
Osoba
Osoba.imie
[o for o in Osoba if o.imie == ['Adam']]
pql_list([o for o in Osoba if o.imie == ['Adam']]).Nazwisko
Pewnie podobieństwo do SBQL można by jeszcze trochę podciągnąć w ramach samego Pythona przeciążając operatory; znacznie więcej dałoby rade pewnie podciągnąć pewnie evalem, ale przecież to nie o to chodziło.
Program jest tutaj. Napisałem go dawno temu (w czasach gdy jeszcze pterodaktyle latały po niebie) i nigdy nie skończyłem ale w sumie mniej więcej działa, a w pliku jest więcej przykładów. Jest tam nawet wstęp do stworzenia kontroli typów i kardynalności atrybutów.