Antwort

6

Wenn ich Ihre Frage richtig verstanden habe, glaube ich nicht, dass eine harte und schnelle Regel. Zum Beispiel können Sie eine funktionale Sprache wie Lisp verwenden, um einen Interpreter für sich selbst zu erstellen. In diesem Fall werden die Implementierungsdetails funktional implementiert (weil Lisp eine funktionale Sprache ist).

Wenn Sie eine Sprache haben, die Turing Complete ist, können Sie damit einen Parser/Interpreter/Compiler für jede andere Sprache implementieren. Es gibt imperative Turing-Complete-Sprachen und funktionale/deklarative Turing-Complete-Sprachen.

Aber alle Code kommt schließlich auf Montage oder Maschinencode, die von Natur aus zwingend erforderlich ist. Theoretisch ist das, was ich oben gesagt habe, wahr, aber anscheinend nicht in der Praxis :).

Als eine interessante historische beiseite, LISP war ein vollständig theoretisches Konstrukt; es war eine mathematische Notation für Computersprachen. Es blieb theoretisch bis LISP der eval Funktion in Maschinencode von Steve Russel auf einem IBM 704 implementiert wurde:

Nach dem, was berichtet von Paul Graham in Hackers & Maler, p. 185, sagte McCarthy: "Steve Russell sagte, schau, warum programmiere ich nicht diese Eval ..., und ich sagte zu ihm, ho, ho, Sie verwirren Theorie mit der Praxis, diese Eval ist für bestimmt Lesen, nicht für das Rechnen. Aber er ging voran und tat es. Das heißt, er kompilierte die Eval in meiner Zeitung in IBM 704 Maschinencode, Fehler zu beheben, und dann beworben dies als ein Lisp-Interpreter, was es war Dieser Punkt Lisp hatte im Wesentlichen die Form, die es heute hat ... " (Schwerpunkt meins)

Also noch einmal, die Feinheiten zwischen Theorie und Praxis. :)

+0

Sie haben Recht, das ist die Bedeutung der Frage. – AwkwardCoder

+0

Aber der Lisp-Interpreter wird dann in Bezug auf Imperativ-Code implementiert. An einem Punkt, wenn Sie nicht auf einem Lisp-Rechner laufen, müssen die Sachen in Assembly kompiliert werden. – dsimcha

+0

Darauf habe ich am Ende meiner Antwort hingewiesen. Wenn du darüber nachdenkst * theoretisch * dann macht es Sinn. Aber in der Praxis nicht so. Zum Beispiel könnte ich einen LISP-Parser in Perl und einen Perl-Parser in LISP implementieren. Wenn man es auf dem Papier anschaut, sieht man im ersten Fall, dass eine funktionale Sprache imperativ umgesetzt wird, während im zweiten Fall eine imperative Sprache funktional implementiert wird. Wenn Sie es jedoch in die Praxis umsetzen, wird es offensichtlich zwingend erforderlich sein, da die Assemblersprache zwingend erforderlich ist. –

3

Die Low-Level-Maschine (CPU, Assembly Language Level) ist zwingend erforderlich, also offensichtlich muss die Implementierung irgendwann dies berücksichtigen. Allerdings benötigt Implementing certain kinds of functional languages like Haskell einige nicht naheliegende Ansätze, um eine Laufzeit mit anständiger Leistung zu schaffen.

Merkwürdigerweise meisten imperative Sprachen gehen durch eine Phase, in der die gesamten Code umgewandelt wird mehr deklarative zu sein:

Hier ist ein Beispiel für die Erstellung Scheme (funktionale) direkt an C-Code (zwingend):

2

Ihre Frage ist ein wenig unklar. Unter der Haube sind Prozessoranweisungen in der Natur zwingend erforderlich. Wenn Ihr Code auf einer von Neumann-Maschine ausgeführt werden soll, sollte er als Imperativ-Code ausgeführt werden.

Es kann möglich sein, eine Maschine (mit einer bestimmten Architektur) zu bauen, die diese Operationen inhärent unterstützt. Tatsächlich wurde LispM entworfen, um zu helfen, Lisp-Programme laufen zu lassen. Obwohl ich mit den Hardware-Eigenschaften von LispM nicht vertraut bin, ist es wahrscheinlich geeignet, einige primitive Operationen auf deklarativer Ebene bereitzustellen.

2

Sind deklarative Sprachen aus imperativen Operatoren aufgebaut? & Funktionen?

Manchmal. Es ist eine Eigenschaft der Implementierung, nicht die Sprache.

In den 1980er Jahren haben viele Leute funktionelle Programme zu Graphen kompiliert und dann die Graphen in einfachere Graphen umgeschrieben. Diese Berechnung beinhaltete normalerweise das Aktualisieren der Graphen an Ort und Stelle, aber ansonsten war es ungefähr so ​​deklarativ, wie Sie möchten. Um mehr zu erfahren, schauen Sie nach "Graph Reduction" oder lesen Sie "Die Viertakt-Reduktions-Engine" von Chris Clack und Simon Peyton Jones.

Schließlich fanden Compiler-Autoren Wege, um eine bessere Leistung zu erzielen, indem sie funktionale Programme direkt mit nativem Maschinencode kompilierten. Wenn die native Maschine eine typische Standardmaschine ist, bedeutet dies typische imperative Operationen. Wenn Sie jedoch die bahnbrechende Arbeit von Professor Arvind am MIT nachschlagen, entwarf und baute seine Gruppe Datenflussmaschinen, in denen die grundlegenden Rechenoperationen deklarativer Natur sind. Es war eine großartige Arbeit, aber all die speziellen Architekturen, die in den 1980er Jahren florierten, sind durch den großen Microsoft/Intel Virtuosenzyklus ausgestorben (mehr Software -> mehr PCs verkauft -> billigere Prozessoren -> mehr PCs verkauft -> .. -> $ 300 Netbooks, die wirklich coole Sachen machen.

0

Implementierung ist das 'unter der Haube versteckt. es kann mit jedem Paradigma aufgebaut werden.

deklarative Programm ist nur eine Daten für seine mehr oder weniger "universelle" imperative Implementierung/VM.

Plus: Angabe nur einer Daten, in einigen hartcodierten (und überprüften) Format, ist einfacher und weniger fehleranfällig als die Angabe Variante eines imperativen Algorithmus direkt. einige komplexe Spezifikationen können einfach nicht direkt geschrieben werden, nur in irgendeiner DSL-Form. beste und freq in DSLs Datenstrukturen verwendet wird Sets und Tabellen. weil Sie keine Abhängigkeiten zwischen Elementen/Zeilen haben. und wenn Sie keine Abhängigkeiten haben, haben Sie die Freiheit zu modifizieren und die Unterstützung zu erleichtern.(vergleiche zum Beispiel Module mit Klassen - mit Modulen die Sie gerne haben und mit Klassen haben Sie ein fragiles Basisklassenproblem) Alle Güter der Deklaration und DSL folgen unmittelbar aus den Vorteilen dieser Datenstrukturen (Tabellen und Sets). ein weiteres Plus - Sie können die Implementierung der deklarativen Sprache vm ändern, wenn DSL mehr oder weniger abstrakt (gut gestaltet) ist. zum Beispiel parallele Implementierung. oder port es zu anderen os etc. alle gut spezifizierten modularen isolierenden schnittstellen oder protokolle gibt ihnen solche freiheit und einfachheit der unterstützung.

Minus: Sie raten richtig. generische (und durch DSL parametrisierte) Implementierung des imperativen Algorithmus/vm kann langsamer und/oder speicherhungriger als spezifische sein. in manchen Fällen. wenn diese Fälle selten sind - einfach vergessen, lass es langsam sein. Wenn es frequency ist - Sie können immer Ihren DSL/VM für diesen Fall erweitern. irgendwo Verlangsamung alle anderen Fälle, sicher ...

P.S. Frameworks ist auf halbem Weg zwischen DSL und Imperativ. und wie alle Lösungen auf halbem Wege ... kombinieren sie Mängel, nicht Vorteile. Sie sind nicht so sicher und nicht so schnell :) Schau dir Jack-of-All-Trades Haskell an - es ist auf halbem Weg zwischen starken einfachen ML und flexiblen Metaprog Prolog und ... was für ein Monster es ist. Sie können Prolog als Haskell mit booleschen Funktionen/Prädikaten betrachten. und wie einfach seine Flexibilität gegen Haskell ist ...

Verwandte Themen