Folgendes berücksichtigen:
if(a == b or c)
In den meisten Sprachen müsste dies wie folgt geschrieben werden:
if(a == b or a == c)
Das ist etwas umständlich und wiederholt Informationen.
Ich weiß, dass meine obige Beispielsyntax etwas klobig ist, aber ich bin sicher, dass es bessere Möglichkeiten gibt, die Idee zu vermitteln.
Warum bieten es nicht mehr Sprachen an? Gibt es Leistungs- oder Syntaxprobleme?
a == b or c
, und es ist meiner Meinung nach nicht einmal gut.Antworten:
Das Syntaxproblem ist - dass es Syntax erfordert.
Unabhängig von der Syntax Ihrer Sprache müssen die Benutzer diese Sprache lernen. Andernfalls laufen sie Gefahr, Code zu sehen und nicht zu wissen, was er tut. Daher wird es im Allgemeinen als eine gute Sache angesehen, wenn eine Sprache eine einfache Syntax hat, die viele Fälle sauber behandelt.
In Ihrem speziellen Beispiel versuchen Sie, einen Infix-Operator (eine Funktion, die zwei Argumente akzeptiert, aber geschrieben ist
Argument1 Operator Argument2
) auf mehrere Argumente zu erweitern. Das funktioniert nicht sehr sauber, da der springende Punkt bei Infix-Operatoren, sofern es einen gibt, darin besteht, den Operator genau zwischen die beiden Argumente zu setzen. Die Erweiterung auf(Argument1 Operator Argument2 MagicallyClearSymbol Argument3...)
scheint nicht viel Klarheit zu schaffenEquals(Arg1,Arg2,...)
. Infix wird normalerweise auch verwendet, um mathematische Konventionen zu emulieren, mit denen Menschen vertraut sind, was für eine alternative Syntax nicht zutreffen würde.Mit Ihrer Idee wären keine besonderen Leistungsprobleme verbunden, außer dass der Parser sich mit einer Grammatik mit einer oder zwei anderen Produktionsregeln befassen müsste, was sich geringfügig auf die Geschwindigkeit des Parsens auswirken könnte. Dies kann für eine interpretierte oder JIT-kompilierte Sprache einen Unterschied machen, aber wahrscheinlich keinen großen Unterschied.
Das größere Problem mit der Idee ist nur, dass es eine schlechte Idee ist, viele Sonderfälle in einer Sprache zu erstellen .
quelle
.
. Also würden sie geschrieben werden alsarg1 op (arg2, arg3)
. Nicht gerade schön, aber an einigen Stellen im Kontext dieser Sprache benötigt.if my_var in (a, b)
dann? Geht es nicht mehr darum, das richtige Werkzeug für den Job zu verwenden?a == b or c
während andere wollena == b or c but not d
. IMO helfen hier Dienstprogrammfunktionen / Bibliotheken.f().Equals(a,b,c)
; könnte ausgewertet werden, da(var temp=f(); temp.Equals(a)||temp.Equals(b)||temp.Equals(c))
diese Syntax perfekt wäre, aber wenn sie ausgewertet wirdint[] arr = {a,b,c}; f().Equals(arr);
, wäre das nicht so gut, insbesondere wenn für jeden Aufruf ein neues Array erstellt werden müsste.Weil es kein Problem ist und das Lösen im Grunde genommen keinen Nutzen bringt, bringt die Implementierung jedoch keine Kosten mit sich.
Bestehende bereichsbasierte Funktionen und solche, die praktisch jede Sprache bietet, können in dieser Situation perfekt funktionieren, wenn sie auf eine Größe skaliert werden, bei der
a == b || a == c
sie nicht abgeschnitten werden.quelle
in_array($a, [$b, $c, $d, $e, $f])
. : PEinige Sprachen haben solche Funktionen. Zum Beispiel können wir in Perl6 Junctions verwenden , die „Überlagerungen“ zweier Werte sind:
Junctions ermöglichen es uns, Operationen an einem Datensatz ziemlich prägnant auszudrücken, ähnlich wie skalare Operationen in einigen Sprachen über Sammlungen verteilt werden. Wenn Sie beispielsweise Python mit numpy verwenden, kann der Vergleich auf alle Werte verteilt werden:
Dies funktioniert jedoch nur für ausgewählte primitive Typen.
Warum sind Kreuzungen problematisch? Da Operationen an einer Junction über die enthaltenen Werte verteilt sind, verhält sich das Junction-Objekt selbst wie ein Proxy für Methodenaufrufe - etwas, das nur wenige Typsysteme außer der Ententypisierung verarbeiten können.
Typsystemprobleme können vermieden werden, wenn solche Junctions nur als spezielle Syntax für Vergleichsoperatoren zulässig sind . In diesem Fall sind sie jedoch so begrenzt, dass sie keinen ausreichenden Mehrwert bieten, um einer vernünftigen Sprache hinzugefügt zu werden. Das gleiche Verhalten könnte durch Festlegen von Operationen oder durch manuelles Schreiben aller Vergleiche ausgedrückt werden, und die meisten Sprachen glauben nicht daran, redundante Syntax hinzuzufügen, wenn es bereits eine perfekte Lösung gibt.
quelle
2 in [1, 2, 3]
. Auf der anderen Seite, wenn Numpy ein.all()
oder etwas hat, ist die äquivalente einfache Python nicht annähernd so prägnant.==
Operator verwendet hat, können wir<
stattdessen auch verwenden - wo ist Ihrin
jetzt? Junctions sind allgemeiner als Set Mitgliedschaft Tests, weil Operationen an der Kreuzung alle Mitglieder verteilen über -(x|y).foo
istx.foo|y.foo
, bis zur Kreuzung schließlich auf einen einzigen Wert reduziert ist. Der bereitgestellte NumPy-Code zeigt eine genau äquivalente, aber ausführlichere Übersetzung der Perl6-Übergänge unter der Annahme primitiver Typen.In Sprachen mit Makros ist es einfach, so etwas hinzuzufügen, wenn es nicht bereits vorhanden ist. Betrachten Sie Schläger
In anderen Sprachen ohne Metaprogrammierung können Sie dies möglicherweise als Überprüfung der Set- / Listenmitgliedschaft umformulieren:
quelle
In einigen (populären) Sprachen ist der
==
Operator nicht transitiv. Zum Beispiel ist in JavaScript0
gleich''
und'0'
, aber dann''
und'0'
sind nicht gleich. Weitere solche Macken in PHP.a == b == c
Dies bedeutet, dass eine weitere Mehrdeutigkeit hinzugefügt wird, da dies zu einem anderen Ergebnis führen kann, je nachdem, ob es als(a == b) & (a == c)
oder interpretiert wird(a == b) & (a == c) & (b == c)
.quelle
In den meisten Sprachen sollte dies trivial durch Schreiben einer
In
Funktion erreichbar sein. Warum sollte sie also Teil der eigentlichen Sprache sein?Linq zum Beispiel hat
Contains()
.Okay, für alle Pedanten ist hier meine Implementierung in C #:
quelle
a == b || a == c
mehrere Male, vielleicht ist es Zeit fürequals_any(a, {b, c})
if (a > (b or c))
und erweiternif (a mod (b or c) == 2)
.i
Variable. Und insgesamt scheint es geschrieben zu sein, nachdem Sie einen langen Tag hinter sich haben :) Weil das Einfügen von beidenreturn true
undreturn false
in die Schleife hier bedeutet, dass es auf keinen Fall über die erste Iteration hinausgeht. Sie vergleichen nur mit dem erstenvalue
. Übrigens, warum nichtAny
wie von @Bob vorgeschlagen verwenden und vereinfachen inreturn values.Any(value => Object.Equals(obj, value));
"if (a == b oder c)" funktioniert in den meisten Sprachen: wenn a == b oder wenn c nicht negativ, null oder null ist.
Sich zu beschweren, dass es ausführlich ist, geht am Punkt vorbei: Sie sollten nicht ein Dutzend Dinge in eine Bedingung stapeln. Wenn Sie einen Wert mit einer beliebigen Anzahl anderer Werte vergleichen müssen, erstellen Sie eine Unterroutine.
quelle
c
sich ein Boolescher Wert ergibt, kann so ziemlich jede Sprache damit umgehena == b || c
:)if(a == b or c)
. Ich muss eine Pause machen, denke ich ...: Pif (a == b or c)
ist ein Pseudocode, um zu prüfen, ob era
gleichb
odera
gleich istc
. Es ist nicht dazu gedacht zu überprüfen, obc
es nicht Null ist.Normalerweise möchten Sie Ihre Syntax auf ein Minimum beschränken und stattdessen zulassen, dass solche Konstrukte in der Sprache selbst definiert werden.
In Haskell können Sie beispielsweise jede Funktion mit zwei oder mehr Argumenten mithilfe von Backticks in einen Infix-Operator konvertieren. So können Sie schreiben:
Dabei
elem
handelt es sich nur um eine normale Funktion, die zwei Argumente verwendet - einen Wert und eine Liste von Werten - und prüft, ob das erste ein Element des zweiten ist.Was ist, wenn Sie
and
anstelle von verwenden möchtenor
? In Haskell können Sie einfach Folgendes verwenden, anstatt darauf zu warten, dass der Compilerhersteller eine neue Funktion implementiert:quelle
Einige Sprachen bieten dies an - bis zu einem gewissen Grad.
Vielleicht nicht als Ihr spezifisches Beispiel, aber nehmen Sie zum Beispiel eine Python-Zeile:
Einige Sprachen eignen sich also gut für mehrere Vergleiche, solange Sie es richtig ausdrücken.
Leider funktioniert es nicht so, wie Sie es für Vergleiche erwarten würden.
"Was meinst du damit, dass es entweder True oder 4 zurückgibt?" - die Miete nach Ihnen
Eine Lösung in diesem Fall besteht zumindest bei Python darin, es etwas anders zu verwenden:
EDIT: Das Folgende würde auch etwas Ähnliches tun, wieder in Python ...
Unabhängig davon, welche Sprache Sie verwenden, kann es sein, dass Sie dies nicht können, sondern dass Sie sich zunächst genauer ansehen müssen, wie die Logik tatsächlich funktioniert. Normalerweise geht es nur darum zu wissen, was Sie tatsächlich von der Sprache verlangen, um es Ihnen zu sagen.
quelle
Die indexOf-Methode, die in einem Array verwendet wird und in fast allen Sprachen verfügbar ist, ermöglicht es, einen Wert mit mehreren anderen zu vergleichen. Ich denke, ein spezieller Operator macht nicht viel Sinn.
In Javascript würde das schreiben:
quelle
Sie fragen, warum können wir das nicht tun:
if(a == b or c)
Python tut dies sehr effizient in der Tat, am effizientesten mit
set
:Beim Testen der Mitgliedschaft prüft 'set', ob die Hashes des Elements identisch sind, und vergleicht erst dann die Gleichheit. Daher müssen die Elemente b und c hashbar sein. Andernfalls wird eine Liste direkt mit der Gleichheit verglichen:
quelle
Mit Sprachen im APL-Stil können Sie einen Skalar mit jedem Element in einem Vektor in einer einzigen Operation vergleichen. Dies erzeugt einen Booleschen Vektor. Zum Beispiel möchte ich schamlos für meinen minimal ausgestatteten apl-Rechner inca ( Online-Dolmetscher ) werben .
Um dies auf einen einzelnen Wert zu reduzieren, können wir ein Inklusivwert oder eine Summierung und Überprüfung auf einen Wert ungleich Null durchführen.
Wie die anderen Antworten sagen, ist das Problem die Syntax. Zu einem gewissen Grad Syntax Lösungen werden gefunden, an den vielleicht hohen Kosten des Arrays Paradigma zu lernen.
quelle