Dynamische Programmiersprache - Dynamic programming language

In der Informatik ist eine dynamische Programmiersprache eine Klasse von höheren Programmiersprachen , die zur Laufzeit viele gängige Programmierverhalten ausführen, die statische Programmiersprachen während der Kompilierung ausführen . Diese Verhaltensweisen können eine Erweiterung des Programms umfassen, indem neuen Code hinzugefügt , Objekte und Definitionen erweitert oder das Typsystem modifiziert wird . Obwohl ähnliche Verhaltensweisen in fast jeder Sprache mit unterschiedlichem Schwierigkeitsgrad, Komplexität und Leistungskosten emuliert werden können, bieten dynamische Sprachen direkte Werkzeuge, um sie zu nutzen. Viele dieser Funktionen wurden zuerst als native Funktionen in der Programmiersprache Lisp implementiert.

Die meisten dynamischen Sprachen sind auch dynamisch typisiert , aber nicht alle. Dynamische Sprachen werden häufig (aber nicht immer) als Skriptsprachen bezeichnet , obwohl sich dieser Begriff im engeren Sinne auf Sprachen bezieht, die für eine bestimmte Laufzeitumgebung spezifisch sind.

Implementierung

Bewertung

Einige dynamische Sprachen bieten eine eval- Funktion. Diese Funktion nimmt einen String-Parameter, der Code in der Sprache enthält, und führt ihn aus. Steht dieser Code für einen Ausdruck, wird der resultierende Wert zurückgegeben. Doch Erik Meijer und Peter Drayton legt nahe , dass Programmierer „Verwendung eval als eines armen Mannes Ersatz für Funktionen höherer Ordnung .“

Objektlaufzeitänderung

Ein Typ- oder Objektsystem kann typischerweise während der Laufzeit in einer dynamischen Sprache geändert werden. Dies kann bedeuten, neue Objekte aus einer Laufzeitdefinition oder basierend auf Mixins bestehender Typen oder Objekte zu generieren . Dies kann sich auch auf das Ändern der Vererbung oder des Typbaums beziehen und damit das Verhalten vorhandener Typen ändern (insbesondere in Bezug auf den Aufruf von Methoden ).

Reflexion

Reflection ist in vielen dynamischen Sprachen üblich und beinhaltet typischerweise die Analyse der Typen und Metadaten von generischen oder polymorphen Daten. Es kann jedoch auch die vollständige Auswertung und Modifikation des Codes eines Programms als Daten beinhalten, wie zum Beispiel die Funktionen, die Lisp bei der Analyse von S-Ausdrücken bietet .

Makros

Eine begrenzte Anzahl dynamischer Programmiersprachen bietet Funktionen, die Code-Introspektion (die Fähigkeit, Klassen, Funktionen und Schlüsselwörter zu untersuchen, um zu wissen, was sie sind, was sie tun und was sie wissen) und eine Bewertung in einer Funktion namens Makros kombinieren . Die meisten Programmierer, die heute den Begriff Makro kennen, sind in C oder C++ auf sie gestoßen , wo sie eine statische Funktion sind, die in einer kleinen Teilmenge der Sprache eingebaut ist und nur String-Ersetzungen im Text des Programms ausführen kann. In dynamischen Sprachen bieten sie jedoch Zugriff auf das Innenleben des Compilers und vollen Zugriff auf den Interpreter, die virtuelle Maschine oder die Laufzeit, wodurch die Definition sprachähnlicher Konstrukte ermöglicht wird, die den Code optimieren oder die Syntax oder Grammatik der Sprache.

Assembly , C , C++ , frühes Java und Fortran fallen im Allgemeinen nicht in diese Kategorie.

Beispielcode

Die folgenden Beispiele zeigen dynamische Funktionen, die die Sprache Common Lisp und ihr Common Lisp Object System (CLOS) verwenden.

Berechnung von Code zur Laufzeit und späte Bindung

Das Beispiel zeigt, wie eine Funktion zur Laufzeit aus berechnetem Quellcode modifiziert werden kann

; the source code is stored as data in a variable
CL-USER > (defparameter *best-guess-formula* '(lambda (x) (* x x 2.5)))
*BEST-GUESS-FORMULA*

; a function is created from the code and compiled at runtime, the function is available under the name best-guess
CL-USER >  (compile 'best-guess *best-guess-formula*)
#<Function 15 40600152F4>

; the function can be called
CL-USER > (best-guess 10.3)
265.225

; the source code might be improved at runtime
CL-USER > (setf *best-guess-formula* `(lambda (x) ,(list 'sqrt (third *best-guess-formula*))))
(LAMBDA (X) (SQRT (* X X 2.5)))

; a new version of the function is being compiled
CL-USER > (compile 'best-guess *best-guess-formula*)
#<Function 16 406000085C>

; the next call will call the new function, a feature of late binding
CL-USER > (best-guess 10.3)
16.28573

Objektlaufzeitänderung

Dieses Beispiel zeigt, wie eine vorhandene Instanz geändert werden kann, um einen neuen Slot einzuschließen, wenn sich ihre Klasse ändert, und wie eine vorhandene Methode durch eine neue Version ersetzt werden kann.

; a person class. The person has a name.
CL-USER > (defclass person () ((name :initarg :name)))
#<STANDARD-CLASS PERSON 4020081FB3>

; a custom printing method for the objects of class person
CL-USER > (defmethod print-object ((p person) stream)
            (print-unreadable-object (p stream :type t)
              (format stream "~a" (slot-value p 'name))))
#<STANDARD-METHOD PRINT-OBJECT NIL (PERSON T) 4020066E5B>

; one example person instance
CL-USER > (setf *person-1* (make-instance 'person :name "Eva Luator"))
#<PERSON Eva Luator>

; the class person gets a second slot. It then has the slots name and age.
CL-USER > (defclass person () ((name :initarg :name) (age :initarg :age :initform :unknown)))
#<STANDARD-CLASS PERSON 4220333E23>

; updating the method to print the object
CL-USER > (defmethod print-object ((p person) stream)
            (print-unreadable-object (p stream :type t)
              (format stream "~a age: ~" (slot-value p 'name) (slot-value p 'age))))
#<STANDARD-METHOD PRINT-OBJECT NIL (PERSON T) 402022ADE3>

; the existing object has now changed, it has an additional slot and a new print method
CL-USER > *person-1*
#<PERSON Eva Luator age: UNKNOWN>

; we can set the new age slot of instance
CL-USER > (setf (slot-value *person-1* 'age) 25)
25

; the object has been updated
CL-USER > *person-1*
#<PERSON Eva Luator age: 25>

Assemblierung von Code zur Laufzeit basierend auf der Klasse der Instanzen

Im nächsten Beispiel erhält die Klasse person eine neue Superklasse. Die Druckmethode wird so umdefiniert, dass sie mehrere Methoden zu einer effektiven Methode zusammenfügt. Die effektive Methode wird basierend auf der Klasse des Arguments und den zur Laufzeit verfügbaren und anwendbaren Methoden zusammengestellt.

; the class person
CL-USER > (defclass person () ((name :initarg :name)))
#<STANDARD-CLASS PERSON 4220333E23>

; a person just prints its name
CL-USER > (defmethod print-object ((p person) stream)
            (print-unreadable-object (p stream :type t)
              (format stream "~a" (slot-value p 'name))))
#<STANDARD-METHOD PRINT-OBJECT NIL (PERSON T) 40200605AB>

; a person instance
CL-USER > (defparameter *person-1* (make-instance 'person :name "Eva Luator"))
*PERSON-1*

; displaying a person instance
CL-USER > *person-1*
#<PERSON Eva Luator>

; now redefining the print method to be extensible
; the around method creates the context for the print method and it calls the next method
CL-USER > (defmethod print-object :around ((p person) stream)
            (print-unreadable-object (p stream :type t)
              (call-next-method)))
#<STANDARD-METHOD PRINT-OBJECT (:AROUND) (PERSON T) 4020263743>

; the primary method prints the name
CL-USER > (defmethod print-object ((p person) stream)
            (format stream "~a" (slot-value p 'name)))
#<STANDARD-METHOD PRINT-OBJECT NIL (PERSON T) 40202646BB>

; a new class id-mixin provides an id
CL-USER > (defclass id-mixin () ((id :initarg :id)))
#<STANDARD-CLASS ID-MIXIN 422034A7AB>

; the print method just prints the value of the id slot
CL-USER > (defmethod print-object :after ((object id-mixin) stream)
          (format stream " ID: ~a" (slot-value object 'id)))
#<STANDARD-METHOD PRINT-OBJECT (:AFTER) (ID-MIXIN T) 4020278E33>

; now we redefine the class person to include the mixin id-mixin
CL-USER 241 > (defclass person (id-mixin) ((name :initarg :name)))
#<STANDARD-CLASS PERSON 4220333E23>

; the existing instance *person-1* now has a new slot and we set it to 42
CL-USER 242 > (setf (slot-value *person-1* 'id) 42)
42

; displaying the object again. The print-object function now has an effective method, which calls three methods: an around method, the primary method and the after method.
CL-USER 243 > *person-1*
#<PERSON Eva Luator ID: 42>

Beispiele

Beliebte dynamische Programmiersprachen sind JavaScript , Python , Ruby , PHP , Lua und Perl . Als dynamische Sprachen gelten im Allgemeinen:

Siehe auch

Verweise

Weiterlesen

Externe Links

(Viele verwenden den Begriff "Skriptsprachen".)