Ich meine es so:
<?php
$number1 = 5; // (Type 'Int')
$operator1 = +; // (Type non-existent 'Operator')
$number2 = 5; // (Type 'Int')
$operator2 = *; // (Type non-existent 'Operator')
$number3 = 8; // (Type 'Int')
$test = $number1 $operator1 $number2 $operator2 $number3; //5 + 5 * 8.
var_dump($test);
?>
Aber auch so:
<?php
$number1 = 5;
$number3 = 9;
$operator1 = <;
if ($number1 $operator1 $number3) { //5 < 9 (true)
echo 'true';
}
?>
Es scheint, als hätten keine Sprachen dies - gibt es einen guten Grund, warum sie das nicht tun?
programming-languages
variables
operators
kgongonowdoe
quelle
quelle
(+)
istNum a => a -> a -> a
IIRC. Sie können auch Funktionen definieren, damit sie (a + b
anstelle von(+) a b
) als Infix geschrieben werden könnenAntworten:
Operatoren sind nur Funktionen unter lustigen Namen mit einer speziellen Syntax.
In vielen Sprachen wie C ++ und Python können Sie Operatoren neu definieren, indem Sie spezielle Methoden Ihrer Klasse überschreiben. Dann arbeiten Standardoperatoren (z. B.
+
) nach der von Ihnen angegebenen Logik (z. B. Verketten von Zeichenfolgen oder Hinzufügen von Matrizen oder was auch immer).Da solche operatordefinierenden Funktionen nur Methoden sind, können Sie sie wie eine Funktion weitergeben:
In anderen Sprachen können Sie neue Operatoren direkt als Funktionen definieren und als Infix verwenden.
Leider bin ich mir nicht sicher, ob PHP so etwas unterstützt und ob es eine gute Sache wäre, es zu unterstützen. Verwenden Sie eine einfache Funktion, die besser lesbar ist als
$foo $operator $bar
.quelle
$
Operator, der Klammern vermeidet (insbesondere mehrere verschachtelte) - aber das kann nur mit non funktionieren -variadic Funktionen, also ohne zB Python und Java. Die Zusammensetzung der unären OTOH-Funktionen ist gut möglich .operator
, mit dem Sie schreiben könnenaction = operator.add
, und dass es für jeden Typ funktioniert, der definiert+
(nicht nurint
).+
die Num-Typenklasse bearbeitet, sodass Sie sie+
für jeden neu erstellten Datentyp implementieren können , aber auf die gleiche Weise, wie Sie alles andere tun, z. B. fmap für einen Funktor. Es ist für Haskell so selbstverständlich, dass der Bediener überlastet werden muss, um dies zu verhindern.$operator1 = +
einen Ausdruck zu schreiben und dann zu verwenden, müssen Sie die Operatorüberladung überhaupt nicht verwenden !Es gibt viele Sprachen, die eine Art Metaprogrammierung ermöglichen . Insbesondere wundert es mich, dass keine Antwort auf die Lisp- Sprachfamilie kommt.
Aus Wikipedia:
Später im Text:
Lisp-Sprachen
Es folgt eine kurze Einführung in Lisp.
Eine Möglichkeit, Code zu sehen, besteht in einer Reihe von Anweisungen: Tun Sie dies, dann tun Sie das, dann tun Sie das andere ... Dies ist eine Liste! Eine Liste der Aufgaben des Programms. Und natürlich können Listen in Listen enthalten sein, um Schleifen usw. darzustellen.
Wenn wir eine Liste stellen die Elemente a, b, c, d wie folgt enthalten: (ABCD) erhalten wir etwas , das aussieht wie ein Funktionsaufruf Lisp, wo
a
die Funktion ist, undb
,c
,d
sind die Argumente. Wenn überhaupt das typische "Hallo Welt!" Programm könnte so geschrieben werden:(println "Hello World!")
Natürlich
b
,c
oderd
könnten Listen sein, die auch etwas zu bewerten. Folgendes:(println "I can add :" (+ 1 3) )
würde dann drucken "" Ich kann hinzufügen: 4 ".Ein Programm ist also eine Serie verschachtelter Listen, und das erste Element ist eine Funktion. Die gute Nachricht ist, dass wir Listen manipulieren können! So können wir Programmiersprachen manipulieren.
Der Lisp-Vorteil
In Lisps ist es nicht nur viel einfacher, neue Operatoren zu erstellen, es ist auch nahezu unmöglich, einige Operatoren in anderen Sprachen zu schreiben, da Argumente ausgewertet werden, wenn sie an die Funktion übergeben werden.
Beispiel: In einer C-ähnlichen Sprache möchten Sie
if
selbst einen Operator schreiben , etwa:my-if(condition, if-true, if-false)
my-if(false, print("I should not be printed"), print("I should be printed"))
In diesem Fall werden beide Argumente in einer Reihenfolge ausgewertet und gedruckt, die von der Reihenfolge der Auswertung der Argumente abhängt.
In Lisps ist das Schreiben eines Operators (wir nennen es ein Makro) und einer Funktion ungefähr dasselbe und wird auf die gleiche Weise verwendet. Der Hauptunterschied besteht darin, dass Parameter für ein Makro nicht ausgewertet werden, bevor sie als Argumente an das Makro übergeben werden. Dies ist wichtig, um einige Operatoren wie die
if
oben genannten schreiben zu können .Realistische Sprachen
Hier wird gezeigt, wie genau dies nicht der Fall ist. Ich empfehle Ihnen jedoch, das Programmieren in einem einzigen Lisp zu versuchen, um mehr zu erfahren. Sie könnten sich zum Beispiel Folgendes ansehen:
Übrigens, Lisp bedeutet LISt Processing.
In Bezug auf Ihre Beispiele
Ich werde Beispiele mit Clojure unten geben:
Wenn Sie eine
add
Funktion in Clojure schreiben können, können(defn add [a b] ...your-implementation-here... )
Sie sie+
so benennen(defn + [a b] ...your-implementation-here... )
. Dies ist in der Tat das, was in der realen Implementierung gemacht wird (der Körper der Funktion ist etwas komplizierter, aber die Definition ist im Wesentlichen die gleiche wie ich oben geschrieben habe).Was ist mit der Infixnotation? Nun, Clojure verwendet eine
prefix
(oder polnische) Notation, so dass wir eininfix-to-prefix
Makro erstellen können, das vorangestellten Code in Clojure-Code umwandelt. Welches ist eigentlich überraschend einfach (es tatsächlich eine der ist Makro - Übungen in dem clojure koans)! Es kann auch in freier Wildbahn gesehen werden, siehe z$=
. B. Incanter- Makro .Hier ist die einfachste Version aus den Koans erklärt:
Um den Punkt noch weiter zu treiben, zitieren einige Lisp :
quelle
if
, aber Sie müssten die Argumentethen
undelse
mit Lambdas umschließen. PHP und JavaScript habenfunction()
, C ++ hat Lambdas, und es gibt eine Apple-Erweiterung für C mit Lambdas.Die meisten Sprachimplementierungen haben einen Schritt, bei dem ein Parser Ihren Code analysiert und daraus einen Baum erstellt. So würde zum Beispiel der Ausdruck
5 + 5 * 8
analysiert werden alsdank des Wissens des Compilers über die Prioritäten. Wenn Sie die Variablen anstelle von Operatoren eingeben, wird die richtige Reihenfolge der Vorgänge vor dem Ausführen des Codes nicht bekannt sein. Bei den meisten Implementierungen wäre dies ein ernstes Problem, daher lassen die meisten Sprachen dies nicht zu.
Sie können sich natürlich eine Sprache vorstellen, in der der Parser das Obige nur als Folge von Ausdrücken und Operatoren analysiert, die zur Laufzeit sortiert und ausgewertet werden. Vermutlich gibt es dafür einfach nicht viel Anwendung.
Viele Skriptsprachen ermöglichen die Auswertung beliebiger Ausdrücke (oder zumindest beliebiger arithmetischer Ausdrücke wie im Fall von
expr
) zur Laufzeit. Dort könnten Sie einfach Ihre Zahlen und Operatoren in einem einzigen Ausdruck kombinieren und die Sprache das auswerten lassen. In PHP (und vielen anderen) wird diese Funktion aufgerufeneval
.Es gibt auch Sprachen, die die Codegenerierung zur Kompilierungszeit ermöglichen. Der mixin Ausdruck in D kommt meiner Meinung nach , wo ich glaube , dass Sie etwas schreiben könnte wie
Hier
operator1
undoperator2
müssten Zeichenkettenkonstanten sein, die zum Zeitpunkt des Kompilierens bekannt sind, z. B. Template-Parameter.number1
,number2
Undnumber3
wurden als normale Laufzeitvariablen gelassen.In anderen Antworten wurde bereits erläutert, wie ein Operator und eine Funktion je nach Sprache mehr oder weniger dasselbe sind. In der Regel gibt es jedoch einen syntaktischen Unterschied zwischen einem eingebauten Infix-Operator-Symbol
+
und einem benannten Callable-Likeoperator1
. Ich werde die Details den anderen Antworten überlassen.quelle
eval()
Sprachkonstrukt möglich " beginnen ... Technisch liefert es genau das gewünschte Ergebnis, das in der Frage gestellt wird.eval
beantwortet diesen Aspekt nicht, daeval
die Operatoren nur Zeichenfolgen sind. Daher begann ich mit einer Erklärung, warum vom Operator eingegebene Variablen Probleme verursachen würden, bevor ich Alternativen diskutiere.Algol 68 hatte genau diese Funktion. Ihr Beispiel in Algol 68 würde so aussehen:
Ihr zweites Beispiel würde so aussehen:
Sie werden feststellen, dass die Operatorsymbole definiert und Methodenkörper zugewiesen sind, die die gewünschte Operation enthalten. Die Operatoren und ihre Operanden sind alle eingegeben, und den Operatoren können Prioritäten zugewiesen werden, damit die Auswertung in der richtigen Reihenfolge erfolgt. Möglicherweise stellen Sie auch fest, dass sich die Schriftart des Operator- und des Variablensymbols geringfügig unterscheidet.
Obwohl die Sprache mit Schriften geschrieben wurde, konnten die Maschinen der damaligen Zeit die Schriften (Papierstreifen und Lochkarten) nicht verarbeiten, und es wurde Stropping verwendet. Das Programm würde wahrscheinlich eingegeben werden als:
Sie können auch interessante Spiele mit der Sprache spielen, wenn Sie Ihre eigenen Symbole für Operatoren definieren, die ich vor vielen Jahren einmal ausgenutzt habe ... [2].
Verweise:
[1] Informelle Einführung in Algol 68 von CHLindsey und SG van der Meulen, Nordholland, 1971 .
[2] Algol 68 Phrases, Ein Tool zur Unterstützung des Compiler-Schreibens in Algol 68 , BC Tompsett, Internationale Konferenz über die Anwendung von Algol 68, 1976 an der University of East Anglia, Norwich, UK .
quelle