Ich habe darüber nachgedacht, wie ich das "perfekte" Bereichsliteral entwerfen würde, wenn ich eine Sprache entwerfen würde. Für Sie, die kein Bereichsliteral in einer Anweisung kennen, die einen Wertebereich wie 1-4 darstellt. Sie werden am häufigsten in for / foreach-Schleifen verwendet
Es scheint ein paar Probleme zu geben, die man berücksichtigen sollte
Die Unterstützung für inklusive und exklusive Bereiche, das Anheften von +1 oder -1 an Endpunkte, scheint etwas umständlich und fehleranfällig zu sein.
Unterstützung für das Steppen, sodass Sie beispielsweise eine Reihe von geraden oder ungeraden Zahlen erstellen können
Lesbarkeit sollte leicht ersichtlich sein, was das Bereichsliteral beschreibt
Eindeutigkeit, es sollte absolut eindeutig sein, was das Bereichsliteral beschreibt
Die Standardeinstellung sollte wahrscheinlich von inklusive bis exklusiv sein, da dies in den meisten Fällen zum Durchlaufen von Arrays usw. verwendet wird.
Ein Beispiel für ein Bereichsliteral, das ich gesehen habe, ist Ruby, das in Form von 1..3 für einen exklusiven Bereich (am Ende) und 1 ... 3 für inklusive (am Ende) vorliegt. Sie können auch 1..10.Schritt (5) ausführen. Nach sorgfältiger Überlegung fand ich jedoch einige Dinge, die mir an diesem Ansatz nicht gefallen haben (aufgrund meiner begrenzten Kenntnisse über Rubin).
Sie können nur inklusive und exklusiv für das Ende beschreiben. Während die meisten Szenarien beschrieben werden, scheint es ein wenig inkonsistent zu sein.
Variiert nur um einen zusätzlichen. scheint ein Rezept zu sein, um schwer zu erkennen, ob ein Sortiment inklusive oder exklusiv ist. Ich weiß nichts über dich, aber Punkte neigen dazu, etwas verschwommen zu werden :)
Das Hinzufügen einer Methode wie der Notation für Bereiche scheint den Begriff eines Literal mit dem einer Klasse zu vermischen, was etwas inkonsistent erscheint (selbst wenn Bereiche zu einer Klasse kompiliert werden).
Wie auch immer, nachdem ich über verschiedene Alternativen nachgedacht habe. Ich habe mir das ausgedacht
- [5..1] 5,4,3,2,1
- [1..5 [ 1,2,3,4
- ] 1..5] 2,3,4,5
- [ 0..5..20] 0,5,10,15,20
und so weiter. Ich mag es, weil [normalerweise ein Set denoniert und dies irgendwie dazu passt, obwohl dies im Gegensatz zu einem Set bestellt werden würde.
Eine Sache, über die ich ein bisschen hin und her gerissen bin, ist, die exklusiven / inklusiven Indikatoren obligatorisch zu machen oder nicht, dh wenn Sie nur 1..5 schreiben, wäre der Standardwert 1,2,3,4, da dies der häufigste Fall bei Arrays usw. Ist Es ist einfacher und lesbarer, aber weniger spezifisch, und wenn Sie schreiben müssen [1..5 [, lernen Sie früh, wie sie funktionieren.
Also, was denkst du, habe ich die meisten Grundlagen abgedeckt, etwas übersehen? Würden Sie das [] obligatorisch machen? Würden Sie Bereichsliterale in Ihrer Programmiersprache anders gestalten?
Kandidaten
- Klammerstil: [0..10 [ , mit Schritt: [0..5..20 [
- Intervallnotation: [0..10) mit Schritt: [0..5..20)
- Ausruf für exklusiv. 0 ..! 10, mit Schritt: 0..5 ..! 20
- mit anderem Schritt. 0 ..! 20, 5
- Dies würde jedoch die Standardeinstellung * 0..10 ' inklusive-inklusive machen
- wortreich: [0 bis! 20 mal 5]
Ich muss sagen, dass mein bisheriger ästhetischer Favorit 0 ..! 10 und 0..5 ..! 20 ist. Ich wünschte nur, die Standardeinstellung 0..10 für inklusive-exklusiv wäre logischer
1,5,10,15,20
Lücke 4, 5, 5, 5?!Antworten:
Warum erfinden, was es in der Mathematik bereits gibt?
Intervall-Notation
Das sollte Ihren Punkt "Eindeutigkeit" abdecken, wie er bereits existiert.
Ihr einziges Problem wäre die Definition des Schrittes. Vielleicht kann etwas anderes in der Mathematik dabei helfen?
quelle
[1..5[
) zu verwenden, verwirrt die Editoren mindestens so sehr wie die Standardintervallnotation.!
Ausschließen des ersten oder letzten Elements kann gut sein.Haben Sie Haskell-Bereiche gesehen? Ihre Idee für Schritte ähnelt Ihrer (in der Mitte), wird jedoch mit einem syntaktischen Unterschied angegeben (aus der Antwort von @ luqui ):
Ich finde diese Notation sehr intuitiv: Sie beginnen mit der Aufzählung und überspringen den Körper, um zu markieren, wo er enden soll.
Es wird nicht der Fall für "exklusiv" behandelt, aber ehrlich gesagt möchte ich das Verhalten lieber einmal klarstellen (angeben, welche Grenze inklusive und welche exklusiv ist), und erwartet, dass der Benutzer Anpassungen vornimmt, es sei denn, die Syntax ist extrem klar (und verwirrt sprachunabhängige Redakteure nicht).
quelle
Sie sollten über Listenverständnisse in Sprachen lesen, die sie anbieten.
Python zum Beispiel deckt Ihre Fälle ziemlich gut mit der
range()
Funktion und dem Listenverständnis für Fälle ab, die zu komplex sind, um sie auszudrückenrange()
.quelle
Ich glaube, Ihre Notation ist weit davon entfernt, eindeutig zu sein. Intuitiv
[0..5..20]
sieht es für mich nicht wie ein Bereich mit Schrittweite = 5 aus. In einigen Eckfällen schlägt es sogar fehl: Was ist mit dem Ausdrücken der Menge (0,2) -[0..2..2]
oder was soll ich in die Mitte setzen?Ich denke, dass Pythons Slice-Notation ein solider Ansatz ist:
[start:end:step]
(Schritt ist optional).Wenn Sie wirklich Unterstützung für exklusive und inklusive Bereiche benötigen, würde ich die Standardbereichsnotation verwenden (dh
(
und verwenden[
), es sei denn, dies führt zu syntaktischen Mehrdeutigkeiten in Ihrer Sprache.quelle
[]
,[[
,]]
und][
, keine Klammer ... und unser Standard ist besser, natürlich;)Ich denke, wenn Sie einen dritten Inkrementwert festlegen, ist es besser, diesen als das Ende und nicht die Mitte hinzuzufügen, da dies ein optionaler Wert ist und erfahrenen Programmierern intuitiver erscheint, als ein optionales drittes Argument in der Mitte hinzuzufügen .
Anstelle von [1..5..20] könnten Sie also etwas wie [1..20] [5] oder [1..20,5] tun.
quelle
Warum nicht einfach [1..4], [2..5], [2..4] verwenden? Das Ausschließen von Bereichen bietet nicht viel Nutzen. Sie müssen nicht MIN + 1 oder MAX-1 schreiben, ja, aber sie verbieten es trotzdem nicht. Zu viel Abwechslung, imho. Meine Sprache der Wahl, Scala, hat (1 bis 3) und (1 bis 3) [= (1 bis 2)], aber es hat mich am Anfang nur verwirrt. Jetzt benutze ich immer 'x bis y' und weiß daher, dass die Option, die ich nicht benutze, die ausschließende ist, aber natürlich profitiere ich nicht von einer Option, die ich nicht benutze.
ist natürlich (1 bis MAX) (x => y = (MAX + 1) - x), aber das ist viel Boilerplate und nicht benutzerfreundlich.
ist natürlich (0 bis 4) (x => y = x * 5) ist nicht so sehr Boilerplate. Umstritten.
quelle
Was ist mit so etwas:
Das
i
unde
im zweiten Paar eckiger Klammern gibt an, ob der Anfang oder das Ende des Bereichs inklusive oder exklusiv ist (oder ob Sie ihn verwenden könntenincl
undexcl
ob Sie klarer sein möchten). Dasby 5
gibt das Schrittintervall an. Das erste und das letzte Beispiel enthalten den ersten und den letzten Wert, daher habe ich das weggelassen[i,i]
, was meiner Meinung nach ein OK-angenommenes Standardverhalten wäre.Standardwerte können
[i,i]
für den Inklusiv- / Exklusivspezifizierer undby 1
für den Schrittspezifizierer sein.Normalerweise hätte ich die Standard - Notation vorgeschlagen beteiligt
(
und[
wie von @ Dan McGrath erwähnt, aber ich stimme zu, dass dies in Code verwirrend aussehen könnte.quelle
Und der Gewinner ist
Es tut mir leid, dass Sie sich für meine eigene Lösung entschieden haben. Ich freue mich über alle Kommentare und Rückmeldungen und kritisiere diese Lösung, wenn Sie etwas falsches daran finden
Also entschied ich mich für:
Wie Sie sehen können, ist Inklusiv die Standardeinstellung für beide Sinne. Dies ist intuitiv am sinnvollsten, insbesondere bei Verwendung von Stepping. Sie können verwenden! ein Ende exklusiv machen.
Der Nachteil ist, dass Sie normalerweise exklusiv verwenden möchten, wenn Sie gegen ein Array arbeiten, aber andererseits sollten Sie in diesen Fällen wahrscheinlich meistens so etwas wie für jeden verwenden. Wenn Sie wirklich wirklich gegen den Index arbeiten müssen, kann der Parser erkennen, wenn Sie möglicherweise die Ausschlussmarkierung am Ende vergessen haben, und eine Warnung ausgeben
Ich habe auf beiden Seiten der Schrittvariablen ... verwendet, anstatt Komma oder irgendetwas anderes zu verwenden, da dies am saubersten aussah und ich hoffe, dass es am besten lesbar ist.
Ich habe auch eine Syntax mit Kommas eingegeben, um Bereiche erstellen zu können, in denen verschiedene Teile unterschiedliche Schritte haben
quelle
Ich würde das Formular '[1..5 [' nicht aus dem gleichen Grund verwenden, aus dem Sie das Mischen von Parens und Klammern vermeiden würden - es wird die Klammerübereinstimmung der meisten vorhandenen Editoren verwirren. Verwenden Sie möglicherweise einen Marker in den geschweiften Klammern, z. B. '[1 .. | 5]'.
Die andere zu berücksichtigende Sache ist das Verhalten von Methoden, um die Grenzen zu erreichen. Zum Beispiel 'begin' / 'end' vs. 'first' / 'last' vs. 'min' / 'max'. Sie müssen sowohl für inklusive als auch für exklusive Limits sowie für solche mit einer Schrittgröße vernünftig sein.
quelle
Ruby hat eine Notation und ein Range- Objekt, das funktioniert. Im Wesentlichen sieht es so aus:
Bei Ruby hängt die Schrittgröße nicht vom Bereich ab, sondern vom Durchlaufen des Bereichs. Wir könnten den gleichen Bereich oben verwenden und ihn anders durchlaufen, wenn wir wollten:
Hier sind also Dinge, die Sie berücksichtigen sollten:
Übrigens sind Bereiche ziemlich nett, wenn Sie zulassen, dass sie wie Ruby in einer switch-Anweisung enthalten sind:
Ich sage nicht, dass Rubys Bereichsobjekt das Ende aller und alles ist, aber es ist eine funktionierende Implementierung des Konzepts, von dem Sie sprechen. Spielen Sie damit, um zu sehen, was Sie mögen, nicht mögen und was Sie anders machen würden.
quelle
Anyways, one example of range literal I've seen is Ruby which is in the form of 1..3 for an exclusive (on the end) range and 1...3 for inclusive (on the end). You can also do 1..10.step(5).
Eine Lösung, die ich sicherlich in Betracht ziehen würde, ist die Verwendung von Operatorüberladung, um z
Es wäre nicht unbedingt sofort für alle transparent, aber wenn sie aufhören und denken, ich hoffe, die meisten Programmierer würden es verstehen, und Leute, die die Sprache regelmäßig verwenden, würden sie einfach als Redewendung lernen.
Zur Verdeutlichung wäre das Ergebnis
[1, 6, 11, 16]
, die Multiplikation und dann die Addition über den Bereich anzuheben. Ich hatte nicht bemerkt, dass es für Python-Benutzer nicht eindeutig sein könnte. Ich stelle mir Bereiche eher als Teilmengen der Gesamtbestellungen als als Listen vor. und das Wiederholen eines Satzes macht keinen Sinn.quelle
list expression * 5
könnte auch "den Wertlist expression
5 mal wiederholen" bedeuten , wie es in Python der Fall ist.1,2,3,1,2,3,1,2,3,1,2,3,1,2,3,1,2,3
?1,3,6,9,12
?5,10,15
? vielleicht noch etwas? In jedem Fall finde ich diese Notation völlig eingängig. Es sieht so aus, als wäre es vielleicht eine seltsame C-Zeiger-Operation ...