Najlepsze pytania
Chronologia
Czat
Perspektywa

Metaprogramowanie

Z Wikipedii, wolnej encyklopedii

Remove ads

Metaprogramowanie – technika umożliwiająca programom tworzenie lub modyfikację kodu innych programów (lub ich samych). Program będący w stanie modyfikować lub generować kod innego programu nazywa się metaprogramem.

Wykorzystanie zasad metaprogramowania pozwala na przykład na dynamiczną modyfikację programu podczas jego kompilacji.

Metaprogramy tworzy się w metajęzykach. Jeśli język jest jednocześnie swoim metajęzykiem, taką cechę nazywamy refleksyjnością (ang. reflexivity).

Metaprogramowanie może polegać nie tylko na generowaniu kodu, ale również na modyfikacjach w czasie wykonania programu. Takie możliwości dają języki Javascript, C#, Lisp, Perl, PHP, Prolog, Python, Ruby, Groovy, Smalltalk, R oraz Tcl.

Remove ads

Przykłady

Przykładem prostego metaprogramu jest ten skrypt w bashu:

#!/bin/bash
# metaprogram
echo '#!/bin/bash' >program
for ((I=1; I<=992; I++)) do
    echo "echo $I" >>program
done
chmod +x program

Program ten generuje 993 linie, wypisujące liczby od 1 do 992. Nie jest to zbyt efektywny sposób na wypisanie liczb 1-992, ale ilustruje, jak w kilka minut można stworzyć program o długości 1000 linii.

Dość analogiczny program w języku python wersji 3.0:

from os import system
clay = open( "adam.py", "w" )
clay.write( "print( \"Madam, i'm Adam.\" )" )
clay.close()
system("python3.0 adam.py")

Jeśli umieścimy powyższy kod w pliku i uruchomimy go, to program wygeneruje plik/program adam.py i uruchomi go, a ten wypisze "Madam, i'm Adam.". Python posiada kilka funkcji ułatwiających metaprogramowanie np. exec() czy execFile().

Poniżej analogiczny kod w scheme:

(define adam "adam.scm") 
(define clay 
	(open-output-file adam))

(display "(display " clay)
(write "Madam, i'm Adam." clay)
(display ")" clay)
	
(close-output-port clay)

(load adam)
Remove ads

Makra lispowe

Podsumowanie
Perspektywa

Dialekty języka Lisp, takie jak Scheme, Clojure czy Common Lisp, jako języki symboliczne, obsługują tzw. makra składniowe. Kod źródłowy zorganizowany jest w nich w postaci tzw. S-wyrażeń i może być po wczytaniu do pamięci zmieniany tak samo, jak inne dane, z użyciem funkcji operujących na jednokierunkowych listach, którymi reprezentowane są złożone S-wyrażenia.

Przykład makra when w Scheme:

(define-macro (when cond . body)
   `(if ,cond
       (begin
          ,@body)))

Przykład makra when w Clojure:

(defmacro when
  [test & body]
  (list 'if test (cons 'do body)))

Powyższe makro działa podobnie do konstrukcji sterującej if, ale ma tylko jedną „odnogę” i można do niej wstawiać wiele wyrażeń. Zapisanie tego kodu w postaci funkcji wywołałoby zarówno warunek, jak i ciało.

Warto zauważyć, że lispowe makra są specyficznymi funkcjami, jednak różnią się od zwykłych funkcji następującymi cechami:

  • Ich podprogramy uruchamiane są zanim dojdzie do uruchomienia programu, a po wczytaniu S-wyrażeń kodu źródłowego, w fazie zwanej makroekspansją.
  • Ich argumenty nie są zachłannie wartościowane przed przekazaniem, lecz ich wartości zawierają podstawiony w miejscach ich przekazania kod źródłowy w postaci struktur danych reprezentujących S-wyrażenia.
  • Zwracane przez nie wartości będą potraktowane jak kod źródłowy, który wstawiony zostanie w miejscach ich wywołań, a następnie poddany procesowi wartościowania wraz z całym programem.
Remove ads

Introspekcja i Refleksja

Są to cechy meta programowania umożliwiające sprawdzanie jak wyglądają obiekty w pamięci np. sprawdzenie listy pól i metod w obiekcie czy pobranie i wywołanie metody, na podstawie wygenerowanego ciągu znaków.

Magiczne metody

Jest to mechanizm występujący m.in. w JavaScript, Python czy PHP umożliwiający zastąpienie wbudowanego mechanizmu własną implementacją np. w php są funkcje takie jak __call czy __get, które wywołają się, gdy próbujemy wywołać metodę lub pobrać właściwość, która nie istnieje. Podobny mechanizm występuje w języku Python. W JavaScript mechanizm ten zaimplementowany jest za pomocą zdefiniowanych symboli oraz obiektów Proxy, które weszły do języka wraz z wersją ES6.

Remove ads

Zobacz też

Loading related searches...

Wikiwand - on

Seamless Wikipedia browsing. On steroids.

Remove ads