Magik – obiektowy język programowania, który obsługuje wielodziedziczenie, polimorfizm i typowanie dynamiczne. Jest on dostarczony przez GE Energy jako część platformy technologicznej Smallworld i został zaprojektowany od początku do realizacji złożonych aplikacji dla przedsiębiorstw użyteczności publicznej takich jak dystrybucja energii i telekomunikacji. Przeznaczony jest do tworzenia aplikacji GIS, stosowany w Smallworld GIS.
Magik (Inspirational Magik) został pierwotnie wprowadzony w 1990 r. i został poprawiony i zaktualizowany na przestrzeni lat. Jego obecną wersją jest 4.0 lub Magik SF (Small Footprint).
Podobieństwo do języka Smalltalk
Magik jest podobny do Smalltalka pod względem cech języka i jego architektury: Programy w Magiku są kompilowane do kodu bajtowego interpretowanego przez maszynę wirtualną Magika. Maszyna wirtualna Magika jest dostępna na wielu platformach, w tym Microsoft Windows i różnych odmianach Uniksa i Linuksa.
Magik opiera się na konsoli i jego kod może być modyfikowany w locie, nawet gdy aplikacja jest uruchomiona. Konsola może być również wykorzystana do wykonania kodu Magika i aby zobaczyć wyniki.
Skompilowany kod jest przechowywany w jednym pliku o nazwie plik obrazu. Każdy plik obrazu trzyma kod bajtowy i stan sesji (np. wartości zmiennych) jaki był gdy obraz został ostatnio zapisany.
Funkcje języka
- Komentarze
Magik używa znaku # do zaznaczania części kodu jako komentarze:
# To jest komentarz.
- Przypisania
Magik używa operatora << aby przypisać:
a << 1.234 b << b + a c << "foo" + "bar" # Łączenie łańcuchów
Dla jasności, ten zapis jest odczytywany jako "a staje się równe 1,234" czy "b staje się równe b plus a". Ta terminologia oddziela przypisanie od porównania.
Magik obsługuje również skompresowaną odmianą tego operatora, który działa w sposób podobny do tych z C:
b +<< a # Odpowiednik b << b + a
- Symbole
Zarówno jak konwencjonalne typy danych takie jak liczby całkowite, zmiennoprzecinkowe i łańcuchy, Magik również implementuje symbole. Symbole są specjalnymi leksemami typu danych które są używane często w Magiku do unikalnej identyfikacji obiektów. Reprezentowane są przez ciąg znaków poprzedzony dwukropkiem. Na przykład:
a << :hello # kiedykolwiek jest napotkane :hello to jest ta sama instancja
- Dynamiczne typowanie
Zmienne Magika nie mają ustalonego typu i mogą odwoływać się do różnych obiektów w czasie wykonania.
Wszystko w Magiku jest obiektem (nie ma rozróżnienia pomiędzy obiektami a prostymi typami jak liczby całkowite):
a << 1.2 # liczba rzeczywista jest przypisana do zmiennej 'a' a << "1.2" # później string jest przypisany do zmiennej 'a'
- Obiekty
Obiekty są implementowane w Magiku przy użyciu egzemplarzy. Egzemplarze są podobne do klas w innych językach programowania takich jak Java, ale mają istotne różnice. Magik obsługuje wielokrotne dziedziczenie i mixiny (które implementują funkcjonalność bez danych). Nowe instancje są tworzone przez klonowanie istniejącej instancji (która zazwyczaj jest egzemplarzem ale nie musi być).
Nowe egzemplarze są tworzone za pomocą instrukcji def_slotted_exemplar(), na przykład:
def_slotted_exemplar(:my_object,
{
{:slot_a, 34},
{:slot_b, "hello"}
}, {:parent_object_a, :parent_object_b})
Ten fragment kodu definiuje nowy egzemplarz zwany my_object który ma dwa sloty (lub pola) zwane slot_a (zainicjowany na 34) i slot_b (zainicjowany na "hello") i dziedziczy z dwóch istniejących egzemplarzy zwanych parent_object_a i parent_object_b.
- Porównanie
Magik implementuje wszystkie zwykłe operatory logiczne (=, <, <=, >, >=, ~=/<>) do porównań, jak również parę niecodziennych. Operatory _is oraz _isnt są używane do porównywania określonych instancji obiektów zamiast wartości.
Na przykład:
a << "hello" b << "hello"
a = b zwraca True (_true) ponieważ wartości a i b są równe a _is b zwraca False (_false) ponieważ a nie jest tą samą instancją co b
a << "hello" b << a = b zwraca True (_true) ponieważ wartości a i b są równe a _is b zwraca True (_true) ponieważ do b przypisaliśmy instancję obiektu a zamiast wartości a.
- Metody
Metody są definiowane w egzemplarzach za pomocą instrukcji _method i _endmethod:
_method my_object.my_method(a, b) _return a + b _endmethod
Jest to konwencja dostarczenia dwóch metod new() (do utworzenia nowej instancji) and init() (do zainicjowania instancji).
# Metoda new _method person.new(name, age) _return _clone.init(name, age) _endmethod
# Metoda inicjalizacji.
_private _method person.init(name, age)
# Wywołanie implementacji rodzica.
_super.init(name, age)
# Inicjalizacja slotów.
.name << name
.age << age
_return _self
_endmethod
Wywołanie _clone tworzy fizyczną kopię obiektu person. Wywołanie _super pozwala obiektom na wywołanie implementacji metody egzemplarza rodzica. Obiekty mogą odwoływać się do siebie używając _self. Sloty obiektu są dostępne i przypisywanie za pomocą notacji z kropką.
Metody które nie są częścią publicznego interfejsu obiektu mogą być oznaczone jako prywatne przy użyciu _private. Prywatne metody mogą być wołane wyłącznie przez _self, _super i _clone.
Opcjonalne argumenty mogą być deklarowane przy użyciu _optional. Opcjonalne argumenty które nie są przekazywane są przypisywane przez Magika do specjalnego obiektu _unset (odpowiednik null). Do deklarowania listy opcjonalnych argumentów może być użyte _gather.
_method my_object.my_method(_gather values) _endmethod
- Iteracja
W Magiku na iteracje pozwalają _for, _over, _loop i _endloop.
_method my_object.my_method(_gather values)
total << 0.0
_for a _over values.elements()
_loop
total +<< a
_endloop
_return total
_endmethod
m << my_object.new() x << m.my_method(1.0, 2, 3.0, 4) # x = 10.0
Tutaj values.elements() jest iteratorem który pomaga iterować wartości.
W Magiku metody generatora są zwane metodami iteratora. Nowe metody iteratora mogą być definiowane za pomocą _iter oraz _loopbody:
_iter _method my_object.even_elements()
_for a _over _self.elements()
_loop
_if a.even? _is _true
_then
_loopbody(a)
_endif
_endloop
_endmethod
- Procedury
Magik obsługuje również funkcje zwane procedurami. Procedury są również obiektami i są deklarowane przy użyciu _proc i _endproc. Procedury są przypisane do zmiennych które mogą być następnie wywoływane:
my_procedure << _proc @my_procedure(a, b, c) _return a + b + c _endproc
x << my_procedure(1, 2, 3) # x = 6
- Dziwactwa językowe
Ponieważ Magik był oryginalnie rozwijany w Anglii, metody w jądrze bibliotek Smallworlda są pisane przy użyciu brytyjskiej odmiany języka angielskiego. Na przykład:
Użyj "initialise" zamiast "initialize".
- Kolekcje
Podobnie jak inne języki programowania Magik też ma kolekcje. Należą do nich:
- Simple Vector
- Rope
- Hash Table
- Property List
- Equality set
- Bags
Przykład Hello World
Oto przykład z Hello world napisany w Magiku:
write ("Hello World!")
Linki zewnętrzne
- Smallworld Product Suite Technology
- MDT - Magik Development Tools IDE dla deweloperów GE Smallworld GIS
- Open Source (SourceForge) biblioteki do Smallworld GIS
- Posty na temat Magika
- Technical Paper No. 5 - Przegląd Smallworld Magik