Otwórz menu główne

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 pisze się w metajęzykach. Jeśli język jest jednocześnie swoim metajęzykiem, to 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 oraz Tcl.

PrzykładyEdytuj

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)

Makra LispoweEdytuj

Języki Lispowe, takie jak scheme czy common lisp, posiadają makra. Dają one możliwości takie jak tworzenie kodu pod postacią ciągu znaków, ale operuje się na kodzie czyli S-Wyrażeniach tak jak na danych. Przykład makra when:

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

Makro działa tak jak if tylko posiada jedną "odnogę" i można do niej wstawiać wiele wyrażeń. Zapisanie tego kodu pod postacią funkcji wywołałoby jednocześnie warunek, jak i ciało.

Introspekcja i RefleksjaEdytuj

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 metodyEdytuj

Jest to mechanizm występujący mi. 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.

Zobacz teżEdytuj