Powershell: Vorschlag: ternäre Bedingungen implementieren

Erstellt am 2. März 2017  ·  52Kommentare  ·  Quelle: PowerShell/PowerShell

Ternäre Konditionale im C-Stil wären eine praktische Ergänzung der Sprache.

Anstatt zum Beispiel zu schreiben:

if ((get-date).tostring("ss") % 2) { 'odd'  } else  { 'even' }

man könnte schreiben:

(get-date).tostring("ss") % 2   ?   'odd'   :    'even'

Es würde auch eine langjährige Enttäuschung lindern:

Bei Microsoft heißt „Versenden wählen“. Eines der Dinge, von denen wir sehr enttäuscht waren, dass wir sie in V1.0 nicht liefern konnten, ist ein ternärer Operator.

Aus einem Blogbeitrag des PowerShell-Teams vom 29. Dezember 2006.


Verwandte: Implementieren von Null-Koaleszenz- und Null-Soaking- und Null-bedingten Zuweisungen

Committee-Reviewed Issue-Enhancement WG-Language

Hilfreichster Kommentar

@RichardSiddaway : Wenn wir uns Stack Overflow bei PowerShell-markierten Fragen ansehen, die _seit 2014 gestellt wurden_, erhalten wir (zum Zeitpunkt des Schreibens):

$PSItem wurde in v3 im September 2012 eingeführt, daher habe ich sicherheitshalber 2014 als Startdatum für die Abfrage gewählt.

Obwohl dies kein exakter Messwert ist, erlaubt Ihnen die Site leider nicht, nach $_ oder _ zu suchen, und ich bin sicher, dass es Fragen gibt, die _weder_ $_ noch $PSItem , und es werden immer noch Fragen vor der Version $_ viel häufiger verwendet wird als $PSItem .

Der größere Punkt ist jedoch, dass Sie nicht _wählen_ müssen:

So wie $PSItem und $_ glücklich nebeneinander existieren, so tun es auch ForEach-Object und % , Where-Object und ? , .. .:

$a ? $b : $c kann mit if ($a) { $b } else { $c } / $(if ($a) { $b } else { $c }) koexistieren

Was die _positiven_ Gründe für die Einführung von $a ? $b : $c angeht?

  • prägnanter, visuell weniger überladen, mit Syntax, die den meisten Programmierern vertraut ist.

  • effizienter, weil $(...) nicht erforderlich ist, die if -Anweisungen benötigen, um ihre Verwendung als Teil eines größeren Ausdrucks zu ermöglichen (der lauter, weniger effizient ist und unbeabsichtigte Seiten haben kann) Auswirkungen)

Was die Bedenken hinsichtlich der Dunkelheit angeht:

Jemand, der _Ausdrücke_ schreibt (im Gegensatz zum bloßen _Aufrufen von Befehlen_ mit (einfachen) Argumenten) kann davon ausgegangen werden, dass er über einige Entwicklererfahrung verfügt, und mein (anekdotischer) Eindruck ist, dass die meisten Entwickler $a ? $b : $c zumindest als komprimiertes if _erkennen

Auch wenn dies nicht der Fall ist, ist es leicht zu erklären, und abgesehen von der Verwendung nicht offensichtlicher _Symbole_ ist die konzeptionelle Komplexität dieselbe wie die eines if ($a) { $b } else { $c } und sogar weniger als
$(if ($a) { $b } else { $c })

Unter der Annahme, dass es sich durchsetzt, wenn es einmal eingeführt wurde - sicherlich zeigt diese Diskussion, dass es Bedarf dafür gibt -, wird es durch häufiges Antreffen zu einem vertrauten und leicht wiedererkennbaren Idiom werden (das heißt prägnanter, einfacher zu tippen und zumindest für mich und ein paar andere .) hier, besser lesbar) - so wie die meisten Leute $_ gegenüber $PSItem bevorzugen.

Alle 52 Kommentare

Beachten Sie, dass mit der Änderung, um Zuweisungen aus Anweisungen zuzulassen, die Notwendigkeit eines ternären Operators reduziert wird. Du kannst einfach machen
$var = if ($x) { $x } else { $y }
Es ist nicht so prägnant wie der ternäre Operator, aber wohl besser lesbar.

Ja, aber Sie müssen immer noch $(...) _zusätzlich_ verwenden, wenn die Bedingung Teil eines größeren Ausdrucks ist:

'The current sec. is ' + $(if ((get-date).tostring("ss") % 2) { 'odd'  } else  { 'even' })

vs.

powershell 'The current sec. is ' + ((get-date).tostring("ss") % 2 ? 'odd' : 'even')

Ich weiß, dass die Lesbarkeit im Auge des ... äh ... Lesers liegt, aber ich persönlich finde letzteres visuell einfacher zu analysieren, und weniger tippen zu müssen ist immer ein Bonus.

Bei einer so häufig verwendeten Funktion denke ich, dass es kein Problem wäre, sich an die abstraktere ternäre Syntax zu erinnern (und die Leute können natürlich weiterhin if , wenn sie es vorziehen).

@mklement0 Ich muss später zustimmen, hat weniger kognitive Belastung.

Das steht definitiv auf meiner Top-Liste.
@BrucePay , gibt es Gründe, warum dies eine schlechte Idee wäre? Oder geht es nur um "Versenden heißt auswählen"?

In der Vergangenheit wurde diese Funktionsanforderung abgelehnt, da sie für weniger erfahrene Skripter schwieriger zu verstehen sei und die Ausdrucksform der if-Anweisung eine klarere, wenn auch ausführlichere Alternative sei.

Meine persönliche Perspektive: Wenn die Sprache nur für mich wäre, hätte ich sie wahrscheinlich schon vor langer Zeit hinzugefügt. Aber ... Ich finde, viele Entwickler verwenden ihn nicht, was tatsächlich darauf hindeutet, dass die Hypothese, dass weniger erfahrene Leute Probleme mit dem ternären Operator haben, etwas Wahres ist.

@lzybkr :

Es lohnt sich, zwischen der _aktiven Nutzung_ einer Funktion und der Fähigkeit, sie zu _erkennen_ und zu verstehen, zu unterscheiden.

Natürlich kann jeder entscheiden, ob er eine solche Funktion verwenden möchte, aber sagen Sie, dass "Probleme damit" bedeutet, dass weniger erfahrene Leute es nicht _verstehen_, wenn sie es im Code anderer sehen?

@mklement0 - wir haben $psitem als Alias ​​für $_ weil genügend Feedback gegeben wurde, dass $_ kryptisch und verwirrend war, daher glaube ich, dass der ternäre Operator für einige weniger schwierig wäre erfahrene Menschen zu verstehen.

Auf der anderen Seite gibt es viele Elemente in PowerShell, die Anfänger oder sogar erfahrene Entwickler verwirren.

Wie bei jeder anderen Sprache erfordert es einige Mühe, die Syntax und Bedeutung von Sprachkonstrukten zu erlernen.
Ich weiß nicht, ob ich denke, dass der ternäre Operator besonders schwer zu verstehen ist.

Haben Sie Daten, die darauf hindeuten?

Ich glaube, die einzigen Daten sind anekdotisch, aber die Kritik gilt für jede kryptische Sprache - Bash, Perl usw.

Und um es klarzustellen, ich habe den historischen Kontext bereitgestellt. Vielleicht ist PowerShell jetzt allgegenwärtig genug, da eine kryptischere Syntax die Akzeptanz nicht beeinträchtigt.

Denken Sie auch daran - einige knappe Sprachen verwenden immer noch if/then als ternären Operator, zB F#.

Trotzdem ist es vielleicht möglich, weniger Zeichen zu verwenden und nicht zu kryptisch zu sein:

if ($x) { $y } else { $z }
$x -then $y -else $z
$x ? $y : $z

-then/-else passt gut zur PowerShell-Syntax - aber ein Operator (oder Operatoren, wenn es zu verwirrend ist, ihn als einen einzelnen Operator vorzustellen), haben Sie den Vorteil, dass Sie keine Klammern und Klammern benötigen.

Andererseits fordert dies ähnliche Probleme wie foreach vs. foreach-object . aber vielleicht ist es nicht so schlimm, ich weiß es nicht.

@lzybkr :

Kryptik in homöopathischen Dosen ist gesund:

PowerShell ist insgesamt lobenswert nicht kryptisch, bietet aber in einigen Fällen eine kryptische Syntax als prägnante _Alternative_ (Sie können auf Wunsch immer noch ausführlich sein) für _häufig verwendete_ Konstrukte, insbesondere ? für Where-Object und % für ForEach-Object .

Im gleichen Sinne ist es, mir $x ? $y : $z als prägnante Alternative zu if ($x) then { $y } else { $z } zur Verfügung zu stellen.

Der kryptische Aspekt wird dadurch abgemildert, dass ? an eine _Frage_ erinnert und daher auf eine Bedingung hindeutet (in diesem Fall allerdings eine _vor der ? ) und – was noch wichtiger ist – _ein potenziell bekanntes Konstrukt aus mehreren ist andere Sprachen_, mit derselben grundlegenden Semantik.

Mit $x -then $y -else $z Sie nicht den gleichen Vorteil: Es ist nicht bekannt.

Auch wenn viele PS-Operatoren symbolische Namen haben, viele nicht: * / + % ...
Auch diese sind von Natur aus kryptisch, wir nehmen sie nur nicht mehr so ​​wahr, weil sie so vertraut und allgegenwärtig sind.

Meiner Meinung nach ist auch $x ? $y : $z vielen bereits bekannt und wird es noch mehr werden, wenn sie einmal in die Sprache eingeführt werden, da häufig prägnante Bedingungen erforderlich sind.

Beachten Sie, dass Sie mit diesem Operator ziemlich eingeschränkt sind. Insbesondere können Sie keine Befehle verwenden, es sei denn, Sie setzen sie in Klammern:

(test-path foo.txt) ? (get-content foo.txt) : (get-content bar.txt)

im Vergleich zu

if (test-path foo.txt) {get-content foo.txt} else {get-content bar.txt}

oder

get-content ((test-path foo.txt) ? "foo.txt" : "bar.txt")

vs

get-content $(if (test-path foo.txt) {"foo.txt"} else {"bar.txt"})

Meiner Meinung nach gibt es wenig Vorteile in Bezug auf die Kürze und einen deutlichen Nachteil in der Lesbarkeit. Der ternäre Operator ist weit weniger interessant, wenn Sie eine ausdrucksorientierte Sprache haben. Als ich vor 16 Jahren mit der Sprache begann, schien das Hinzufügen des ternären Operators aus einem C-Hintergrund zu kommen. Jetzt bin ich froh, dass wir es nie hinzugefügt haben. Es fühlt sich einfach an wie Unordnung.

Insbesondere können Sie keine Befehle verwenden, es sei denn, Sie setzen sie in Klammern:

Das gilt für _jeden_ PowerShell-Operator.

Nicht alle PowerShell-Anweisungen beinhalten Befehle, und wenn dies der Fall ist, wissen die Benutzer bereits, dass (...) (in den meisten Fällen) der Eintrittspreis für Befehle ist.

In Ihrem eigenen Beispiel schlägt für mich ((test-path foo.txt) ? "foo.txt" : "bar.txt") $(if (test-path foo.txt) {"foo.txt"} else {"bar.txt"}) , sowohl wegen der Dunkelheit, dass $(...) benötigt wird, als auch wegen des durch die geschweiften Klammern verursachten Rauschens.

Vielleicht liegt es nur an mir, aber ich finde das:

get-content ((test-path foo.txt) ? "foo.txt" : "bar.txt")

viel einfacher visuell zu scannen/zu analysieren als dies:

get-content $(if (test-path foo.txt) {"foo.txt"} else {"bar.txt"})

Meine einzige Beschwerde zu diesem Problem ist, dass Sie, wenn Sie ternäres ?: ausführen möchten, auch ?? Null-Koaleszieren ausführen sollten:

$logDir = $env:LogDir ?? "$PSScriptRoot\Log"

Ich habe eine Reihe von Invoke-Ternary- und Invoke-NullCoalescing-Implementierungen in freier Wildbahn gesehen (zB https://github.com/dahlbyk/posh-git/blob/master/src/Utils.ps1#L12). Dies deutet darauf hin, dass ein allgemeiner Wunsch nach einer solchen Funktion besteht, die in die Sprache eingebettet ist.

@rkeithhill : Ich stimme zu; re Null-Coalescing: Es gibt bereits ein Problem, das auch Null-Soaking abdeckt: #3240

Das Argument weniger erfahrener Programmierer wäre also nicht einfach in der Lage, eine null-koaleszierende oder ternäre Code-Anweisung zu verwenden, denke ich, ist ein wenig kurzsichtig. Es besteht keine Notwendigkeit, diese "fortgeschrittenen" Funktionen zu verwenden, und wenn ein Programmierer den Code nicht lesen kann, weil ihm die Erfahrung fehlt, dann ist das mein Stichwort, dass ich sehr schnell etwas Neues lernen muss.
Als ich zum ersten Mal einen Ternary in C# sah, dachte ich, dass WTF diese frische Hölle von MS eingeführt hat, bis ich mir ein paar Minuten Zeit nahm, um mich darüber zu informieren, was mich dann begeisterte.

Praktisches Beispiel in POSH, ich habe diese Zeile:
$mc_object = ($Message.fields | where Name -Match appname).Content
Das ist in Ordnung und gut, außer wenn das $Message-Objekt keine Dateieigenschaft mit dem Namen "App-Name" hat und da ich die JSON-formatierten Daten, aus denen diese stammen, nicht kontrolliere, muss ich bestimmen, was zu tun ist.

Bei einer Null-Coalesce-Operation muss ich also nur ?? "" am Ende hinzufügen, um sicherzustellen, dass das $mc_object immer eine gültige Zeichenfolge war, selbst wenn der ursprüngliche Setter null war. Andernfalls müsste ich verschiedene Techniken anwenden, um das zu erreichen, was 4 Tastenanschläge bewirken können, wie z
$mc_object = if(-not ($Message.fields | where Name -Match appname).Content)){""}else{($Message.fields | where Name -Match appname).Content}
Das ist für mich sehr unlesbar, aber dann kann ich das ein bisschen aufräumen, indem ich so etwas mache, was ich tue.
$mc_object = ($Message.fields | where Name -Match appname).Content if(-not $mc_object){$mc_object = ""}

Es ist zwar nicht schrecklich, aber es sind verdammt viel mehr als 4 Tasten, die gedrückt werden, um sich zu nullen.

Wie auch immer, ich stimme definitiv für ternär und null-coelasce in Powershell, es fügt einige sehr fortschrittliche Funktionen hinzu und macht Powershell für die Verwendung in der "Kern" -Form auf jedem System attraktiver.

@lzybkr Ich habe noch niemanden gesehen, der tatsächlich $PSItem adoptiert hat. Ich arbeite in einem recht großen Team von Leuten, die Skripte schreiben, und alle verwenden immer noch $_ , sogar die weniger erfahrenen PowerShell-Benutzer.

@tibmeister oder....

if (-not ($mc_object = $Message.fields.where{$_.Name -match 'appname'}.Content)) {
    $mc_object = ''
}

Zuweisungen als Ausdrücke werden durchgereicht, sind aber unglaublich unlesbar.

Ich benutze regelmäßig $psitem

Über mehrere Jahre hinweg wurde $psitem in der Bewertung von Scripting Games häufig in den Antworten verwendet

@RichardSiddaway : Wenn wir uns Stack Overflow bei PowerShell-markierten Fragen ansehen, die _seit 2014 gestellt wurden_, erhalten wir (zum Zeitpunkt des Schreibens):

$PSItem wurde in v3 im September 2012 eingeführt, daher habe ich sicherheitshalber 2014 als Startdatum für die Abfrage gewählt.

Obwohl dies kein exakter Messwert ist, erlaubt Ihnen die Site leider nicht, nach $_ oder _ zu suchen, und ich bin sicher, dass es Fragen gibt, die _weder_ $_ noch $PSItem , und es werden immer noch Fragen vor der Version $_ viel häufiger verwendet wird als $PSItem .

Der größere Punkt ist jedoch, dass Sie nicht _wählen_ müssen:

So wie $PSItem und $_ glücklich nebeneinander existieren, so tun es auch ForEach-Object und % , Where-Object und ? , .. .:

$a ? $b : $c kann mit if ($a) { $b } else { $c } / $(if ($a) { $b } else { $c }) koexistieren

Was die _positiven_ Gründe für die Einführung von $a ? $b : $c angeht?

  • prägnanter, visuell weniger überladen, mit Syntax, die den meisten Programmierern vertraut ist.

  • effizienter, weil $(...) nicht erforderlich ist, die if -Anweisungen benötigen, um ihre Verwendung als Teil eines größeren Ausdrucks zu ermöglichen (der lauter, weniger effizient ist und unbeabsichtigte Seiten haben kann) Auswirkungen)

Was die Bedenken hinsichtlich der Dunkelheit angeht:

Jemand, der _Ausdrücke_ schreibt (im Gegensatz zum bloßen _Aufrufen von Befehlen_ mit (einfachen) Argumenten) kann davon ausgegangen werden, dass er über einige Entwicklererfahrung verfügt, und mein (anekdotischer) Eindruck ist, dass die meisten Entwickler $a ? $b : $c zumindest als komprimiertes if _erkennen

Auch wenn dies nicht der Fall ist, ist es leicht zu erklären, und abgesehen von der Verwendung nicht offensichtlicher _Symbole_ ist die konzeptionelle Komplexität dieselbe wie die eines if ($a) { $b } else { $c } und sogar weniger als
$(if ($a) { $b } else { $c })

Unter der Annahme, dass es sich durchsetzt, wenn es einmal eingeführt wurde - sicherlich zeigt diese Diskussion, dass es Bedarf dafür gibt -, wird es durch häufiges Antreffen zu einem vertrauten und leicht wiedererkennbaren Idiom werden (das heißt prägnanter, einfacher zu tippen und zumindest für mich und ein paar andere .) hier, besser lesbar) - so wie die meisten Leute $_ gegenüber $PSItem bevorzugen.

mklement0, Sie haben ein sehr tolles Beispiel und ich denke, es zeigt den Punkt klar, danke.

Wenn ich dies noch einmal lese und überarbeite und mir einige der Fragen ansehe, tendiere ich eher zu den etwas ausführlicheren vorgeschlagenen Syntaxen:

$value = $a -eq $b -then $trueVal -else $falseval

oder für eine semantisch lesbarere Syntax:

$value = $trueVal -if $a -eq $b -else $falseVal

@vexx32 Ihr erstes Beispiel

Ja, ich glaube , ich eher zustimmen, aber es liest etwas mehr ... reibungslos. Aber ich würde immer noch zum ersten gehen.

Da PowerShell als "On-Ramp"-Sprache für C# gedacht ist, denke ich, dass die Verwendung von ? : der richtige Weg ist. Sogar JavaScript verwendet diese Syntax und sie ist heutzutage eine der beliebtesten Sprachen. :-)

Einverstanden, @rkeithhill , sowohl wegen der Vertrautheit des Konstrukts aus mehreren anderen Sprachen _und_ dem Wunsch, auch null-koaleszierende, null-soakende und null-bedingte Zuweisungen zu haben , die in C# ebenfalls auf ? basieren.

Die letzteren beiden - zB $foo?.bar und $var ?= 'default val' - sind ohne eine symbolbasierte Darstellung nicht wirklich möglich, und sogar für Null-Koaleszenz scheint $a ?? 'value-if-null' etwas wie $a -elseifnull 'value-if-null' vorzuziehen.

Denken Sie daran, dass ? als häufig verwendeter Alias ​​für Where-Object bereits als _conditional_ fest verankert ist, so dass die Übertragung dieses Wissens auf Variationen seiner Verwendung logisch erscheint.

Ist PowerShell wirklich ein Einstieg in C#? Ich weiß, dass dies vor 10-12 Jahren eine erklärte Absicht war, aber passiert es wirklich? Mein Verdacht ist, dass C# für die Mehrheit der PowerShell-Benutzer nicht das richtige Ziel ist.

Wenn ternäre Bedingungen auftreten, würde ich lieber so etwas sehen wie
$value = $trueVal -if $a -eq $b -else $falseVal

wie erwähnt von @vexx32

Für den durchschnittlichen PowerShell-Benutzer ist es sinnvoller.

@mklement0 Meine Kommentare zu $psitem basieren auf meiner persönlichen Erfahrung. Wenn Sie eine andere Erfahrung gemacht haben, macht dies meine Erfahrung nicht ungültig

Ich weiß, dass das vor 10-12 Jahren eine erklärte Absicht war

Ja, bei den frühen MVP-Gipfeln unter anderem von Jeffrey. Seitdem habe ich nichts anderes mehr gehört.

Außerdem nehmen fast alle Bedingungs-/Schleifenkonstrukte von C# (und der C-Linie), if {} , while {} , do {} while , switch {} , for {} , foreach {} , try {} catch {} finally {}`. Es macht für mich Sinn, dass dieses bedingte Konstrukt auch würde.

Das sind jedoch Sprachschlüsselwörter, @rkeithhill. Betreiber sind ganz anders.

Ich denke, Sie werden feststellen, dass sich die überwiegende Mehrheit der in PowerShell verwendeten Operatoren stark von ihren C#-Äquivalenten unterscheidet. Das PS-Team hat sich bei den meisten Operatoren ganz klar für eine beschreibendere Syntax entschieden.

Ich denke, dass ternäres Verhalten auch nach den ausführlicheren verfügbaren Syntaxoptionen erfolgen sollte. PowerShell wurde möglicherweise als "Aufstieg" zu C# konzipiert, aber das bedeutet nicht, dass es seine eher symbolischen Syntaxen erben sollte. Tatsächlich gibt es viele Orte, an denen dies sorgfältig vermieden wurde .

Bedenken Sie, dass Ihre Argumente für die symbolische Syntax darin verwurzelt sind, wie andere gängige Programmiersprachen dieses Konzept darstellen. Powershell ist nicht gewesen , dass die Route in der Post zu gehen, anstatt liebe Arbeit mit als beschreibender Syntax wie sinnvoll gemacht werden. Nur weil Anwender, die bereits Erfahrung mit C# haben, mit einer solchen Syntax vertraut sind, ist das sicherlich kein Grund, sie zu verwenden.

Wenn Powershell eine ‚On-Rampe‘ Sprache C # oder eine andere Sprache ist (was, glaube ich, hat es ziemlich gut auf diesem weit) , dann müssen wir die kleinsten gemeinsamen Nenner hier betrachten und darüber nachdenken , was die unerfahrenen Personen finden würden sinnvoll und intuitiv .

Ich sage nicht , meine dargebotene Lösungen sind, aber ich glaube , sie möglicherweise in einer sinnvolleren Richtung aus dieser Perspektive geleitet.

@vexx32
Wie sieht es mit diesen Betreibern aus?

.
=
[]
,
+ - * / %
++ --
+=  -=  *=  /= %=

Im Allgemeinen stimme ich zu, dass es nicht immer angemessen ist, den Anweisungen von C# zu folgen, und dass die Bewahrung des Geists von PowerShell Vorrang haben sollte.

Umgekehrt würde ich davon abraten, von C# abzuweichen, wenn die gleiche Syntax plausibel erscheint, und mir ist der vorliegende Vorschlag - zusammen mit #3240 - ein Beispiel dafür.

Wenn wir andere Sprachen beiseite lassen:

  • Die aktuelle Semantik von ? erstreckt sich plausibel auf die vorgeschlagenen Operatoren.

  • Wenn Sie einen Wert in den vorgeschlagenen _related_ Operatoren sehen - Null-Soaking ( ?. ), Null-Coalescing ( ?? ) und Null-bedingte Zuweisung ( ?= ) - dann entscheiden Sie sich für eine ausführliche ternäre Form wie -then / -else ist keine Option, wenn Sie möchten, dass alle diese verwandten Operatoren eine Gemeinsamkeit widerspiegeln (die sie offensichtlich konzeptionell haben).

Je exotischer ein Feature ist, desto wichtiger ist die Ausführlichkeit.

Je häufiger ein Feature verwendet wird, desto prägnanter ist es. Und die Abstraktheit einer symbolbasierten Darstellung ist durch die bloße wiederholte Auseinandersetzung mit der Syntax kein Problem mehr - wie beispielsweise bei * .

Alle mit mir besprochenen Operatoren fallen in die letztere Kategorie.


@RichardSiddaway :

Meine Kommentare zu $psitem basieren auf meiner persönlichen Erfahrung. Wenn Sie eine andere Erfahrung gemacht haben, macht dies meine Erfahrung nicht ungültig

Ja, Ihre Kommentare basieren auf _persönlichen_ Erfahrungen.
Meine basierten auf der _Analyse von Daten_ der beliebten Q & A-Site Stack Overflow, um _allgemeine_ Nutzungsmuster (innerhalb der angegebenen Einschränkungen) abzuleiten - was nichts mit meiner persönlichen Erfahrung zu tun hat.

Der einzige Grund, warum Sie meine Kommentare als ungültig ansehen könnten, wenn Sie glauben, dass Ihre persönlichen Beobachtungen eine "transpersonale" Wahrheit widerspiegeln - eine Behauptung, die Sie in Ihren Kommentaren nicht als solche geltend gemacht haben. Wollten Sie es schaffen? Wenn ja, müssen wir _das_ besprechen.

Fast alle diese Operatoren sind mathematische Operatoren mit relativ klarer Bedeutung, @mklement0 😄

Ein ternärer Operator ist ein bedingter Operator, und _alle_ der Booleschen/Bedingten Operatoren von PS haben die ausführlichere Form: -and , -or , -eq , -ne , -contains usw.

Ich stimme zu, dass diese Abkürzung jedoch aufgrund der Notwendigkeit der umgebenden Funktionen und der zugehörigen Operatoren sinnvoll sein kann. Aber ich denke, dass die "standardmäßige" ternäre Syntax für diejenigen von uns, die ihr nicht schon wiederholt ausgesetzt waren, nicht besonders intuitiv ist.

Operatoren sind mathematische Operatoren

Von den aufgeführten haben nur + - * / % (rein) mathematische Bedeutung, aber der klar verstandene Aspekt gilt auch für die anderen (mit Ausnahme von = , da er oft mit Gleichheitsprüfungen verwechselt wird ).

Das bessere Konstrukt zum Vergleichen von <condition> ? <if-true> : <else> ist das if _statement_, nicht andere Operatoren. Während if definitiv ausführlicher ist, ist es genau dieser Aspekt, den die ternäre Operation ansprechen soll (zusätzlich dazu, dass es sich um einen echten, zusammensetzbaren Ausdruck handelt, im Gegensatz zu if ).

Es gibt sicherlich ein Spektrum an Prägnanz, aber, wie Sie sagen, um alle verwandten Operatoren auf konsistente Weise unterzubringen, ist eine symbolbasierte Syntax sinnvoll.

für diejenigen von uns, die ihm nicht schon wiederholt ausgesetzt waren.

Nun, das wird sich hoffentlich bald ändern. 😁
Punkt genommen, aber (a) die Syntax ist leicht zu erklären und hat die gleiche konzeptionelle Komplexität wie eine if Anweisung, und (b) wiederholte Exposition sollte bei der Gedächtnisspeicherung helfen.

@mklement0 Wie schlagen Sie vor, dass ? ein gültiges Namenszeichen ist ? Wandel brechen? Ich halte Leute für Powershell-Core für gut versiert mit Powershell, so wie es ist, und dass zusätzliche Syntax (die in anderen Sprachen seit fast 50 Jahren existiert) kein Hindernis sein wird. Sie können immer if/else wenn sie mehr Ausführlichkeit wünschen.

? ist nur im Befehlsmodus ein gültiger Alias; in allen Varianten des Ausdrucksmodus ist es derzeit einfach ein ungültiges Zeichen. Es gibt keine Kollision.

Wenn Sie versuchen, diesen Code einzugeben, wird einfach ein Fehler ausgegeben:

$Value = $true
$Value ? "Hello!" : "Goodbye!"

Ergebnis:

At line:1 char:8
+ $Value ? "Hello!" : "Goodbye!"
+        ~
Unexpected token '?' in expression or statement.
+ CategoryInfo          : ParserError: (:) [], ParentContainsErrorRecordException
+ FullyQualifiedErrorId : UnexpectedToken

@vexx32

$what? # <- example of a valid variable name

In seinem mit Nullen durchtränkten Beispiel: $var?.maybenull() kümmert sich nicht darum, dass dort ein Fragezeichen steht, und wenn jemand versucht, übermäßig komprimiert zu sein, wird sein Ternär kaputt gehen.

Entschuldigung, das wurde hauptsächlich in der anderen Ausgabe darüber diskutiert, daher dachte ich nicht, dass Sie sich darauf beziehen.

Ob wir ausschließen können, dass es sich um ein gültiges Zeichen mit variablem Namen handelt oder nicht, liegt am PS-Team, aber ich bin der Meinung, dass es nicht viel schaden würde, es zu verhindern, dass es standardmäßig als Zeichen mit variablem Namen angesehen wird. Ich glaube nicht, dass ich jemals gesehen habe, dass jemand ? als Teil eines Variablennamens verwendet hat.

@vexx32 Ja, ich sollte das da

$var = $test?$thing1:$thing2

aber ich spalte vielleicht zu sehr die Haare an den Randfällen für diejenigen von uns, die in der Muschel leben.

Korrigiert:

$var = ${test}?${thing1}:$thing2

@mklement0 - Ich stimme nicht unbedingt zu:

Das bessere Konstrukt zum Vergleichen?:to ist die if-Anweisung, nicht andere Operatoren. Während if definitiv ausführlicher ist, ist es genau dieser Aspekt, den die ternäre Operation ansprechen soll (zusätzlich dazu, dass es sich um einen echten, zusammensetzbaren Ausdruck handelt, im Gegensatz zu if).

Der ternäre Operator existiert insbesondere, weil C/C# anweisungsorientierte Sprachen sind, aber bedingte Ausdrücke benötigt werden.

In ausdrucksorientierten Sprachen (zB F# oder Rust) gibt es keine knappe Syntax, da sie als unnötig erachtet wird. Ich denke, diese alte Diskussion über Rust , die den ternären Operator entfernt, ist interessant.

Eine Sache, die ich in Rust sehr mag, ist die Verwendung des Operators ? für die Fehlerbehandlung. Ich habe keinen konkreten Vorschlag, ? in PowerShell zu verwenden, aber ich habe das Gefühl, dass ? besser für die Fehlerbehandlung als für einen bedingten Ausdruck verwendet werden könnte.

@TheIncorrigible1 , @vexx32 : Ja, Null-Soaking wäre technisch gesehen ein Breaking Change, aber hoffentlich vom Typ Bucket 3 (in der Tat, lassen Sie uns die Diskussion dort fortsetzen); für die ternäre Operation scheint die vorgeschlagene Verwendung von {...} / Leerzeichen vor ? zur Begriffsklärung dieses Problem zu lösen.

@lzybkr :

Der ternäre Operator existiert insbesondere, weil C/C# anweisungsorientierte Sprachen sind, aber bedingte Ausdrücke benötigt werden.

Nun, in PowerShell sind Flusssteuerungsanweisungen wie if _halbe_-Ausdrücke; in _einfachen_ Ausdrücken wäre die vorgeschlagene ternäre Operation äquivalent; in _verschachtelten_ einsen würde es nicht:

$foo = $True  ?     1   :      0    # proposed ternary
$foo = if ($True) { 1 } else { 0 }  # equivalent `if` statement
$foo = 1 + ($True  ?     1   :      0)   # nesting OK; note that + would have higher precedence
$foo = 1 + if ($True) { 1 } else { 0 }  # !! doesn't work
$foo = 1 + (if ($True) { 1 } else { 0 })  # !! doesn't work, even with parentheses
$foo = 1 + $(if ($True) { 1 } else { 0 })  # only $(...) (and situationally @(...)) work

Die Notwendigkeit von $() / @() ist mehr als nur eine Syntax-Unannehmlichkeit: Es hat Auswirkungen auf das Verhalten und die Leistung.

Trotzdem _wünsche ich_, dass Anweisungen wie if und foreach ehrliche Ausdrücke sind (zwei weitere Beispiele für Dinge, die derzeit fehlschlagen: foreach ($i in 1..5) { $i } | Write-Output oder foreach ($i in 1..5) { $i } > out.txt ).
Ich weiß nicht genug, um zu beurteilen, ob sie _nicht sein können_ und/oder ob es Bedenken hinsichtlich der Abwärtskompatibilität gibt.
Siehe auch: #6817


Wenn if in PowerShell ein vollständiger Ausdruck werden sollte, dann könnten Sie das Argument, das zur Entfernung der ternären Bedingung aus Rust geführt hat, machen: sie ist dann nicht mehr _notwendig_.

Meine Motivation für diesen Vorschlag war jedoch nie _Notwendigkeit_ - es geht um Prägnanz, Bequemlichkeit und Lesbarkeit (visuelles Durcheinander).


Ich habe keinen konkreten Vorschlag zur Verwendung ? in PowerShell, aber es fühlt sich an wie ? besser für die Fehlerbehandlung als für einen bedingten Ausdruck verwendet werden könnte.

Ich denke, dass die Einführung von ? mit einer grundlegend anderen Semantik als in C# eine Quelle ewiger Verwirrung wäre.

Unabhängig davon sind Verbesserungen der Fehlerbehandlung von PowerShell eine Diskussion wert.

Wenn wir nach einer knappen, aber wenig intuitiven Alternative zu If/Then/Else suchen, haben wir bereits eine.

( 'False', 'True' )[( Test-Condition )]

Und es funktioniert in Ausdrücken.

"This statement is " + ( 'False', 'True' )[( Test-Condition )]

@TimCurwick : Das ist prägnant (und undurchsichtiger), aber nicht äquivalent: Die vorgeschlagene ternäre Bedingung wäre _kurzschluss_ (genau wie eine if Anweisung), während Ihre Syntax ausnahmslos _beide_ Alternativen auswertet.

Allerdings ist Ihre Syntax sicherlich die zweitbeste, die derzeit verfügbar ist, vorausgesetzt, man ist sich der angegebenen Einschränkung bewusst.

Hat jemand in Bezug auf die Diskussion, wie ternäre Auswahlmöglichkeiten in PowerShell angezeigt werden, eine Option im gleichen Format wie -replace / .replace() in Betracht gezogen?

$a -eq $b -ternary $a,$c
$true -ternary 1,0

oder

($a -eq $b).ternary($a,$c)
($true).ternary(1,0)

Dies würde deutlich machen, dass der Operator eine ternäre Aktion durchführt, indem er sie wörtlich ternär nennt. Es ist ausführlich, aber immer noch kurz zu schreiben, und es nutzt das vorhandene allgemeine Verhalten von -operator $first,$second , sodass es sich für Powershell-Benutzer mit allen Erfahrungsbereichen vertraut anfühlen sollte

🤔 Es könnte funktionieren, aber es wäre umständlicher als jede der vorgeschlagenen Alternativen. -replace funktioniert so, weil es nur ein tatsächliches Array von Argumenten akzeptiert. .Replace() wird nicht vom PS-Team verwaltet – es ist eine Methode der .NET-Klasse System.String .

Wenn wir versuchen würden, eine dieser Syntaxen zu verwenden, würde dies entweder eine ETS-Methode bedeuten (die in Ordnung ist, aber dazu neigt, ein wenig Performance-Overhead bei der Erstellung von Objekten zu verursachen, an die sie angehängt werden muss) oder mit der Operatorversion Sie vorschlagen, könnten wir nicht ohne weiteres ein Array als Argument haben.

Ohne einen solchen Operator im Parser in Sonderform zu setzen, wären wir nicht in der Lage, kurzzuschließen. Ternäre Syntaxen in anderen Sprachen existieren im Allgemeinen, weil Sie _nicht wollen_, beide Optionen tatsächlich auszuwerten; die Rechenzeit ist schneller, wenn nur der richtige Zweig ausgewertet werden muss, anstatt beide Optionen vollständig auszuwerten (was mit einigen erheblichen Nebenwirkungen verbunden sein kann).

Und da dies bereits eine spezielle Groß-/Kleinschreibung erfordern würde, wäre es effektiver, eine neue Syntax dafür einzuführen, um Verwirrung zu vermeiden (es wäre ein bisschen irreführend, etwas zu haben, das wie ein Array aussieht, aber nicht wie eines verwendet werden kann; es würde es nicht unterstützen, das "Array" im Voraus zu erstellen und beispielsweise als Variable zu übergeben). Die Tatsache, dass Methodenargumente bereits ein wenig mit der Array-Syntax in Konflikt geraten, ist oft schon irreführend. Ich glaube nicht, dass ich dem Mix ein Verhalten der _dritten_ Variante für Kommas hinzufügen möchte.

@PowerShell/powershell-committee hat dies ausführlich diskutiert, wir sind uns nicht alle einig, aber eine Mehrheit ist sich einig, dass es einen Wert hat, diesen Operator zu haben und sich an die C#-Syntax anzupassen, wobei ?: beibehalten wird, da erwartet wird, dass dies bei der meisten Verwendung der Fall ist von C#-Entwicklern sein. Diese Funktion wird experimentell sein, bis Feedback zur tatsächlichen Nutzung vorliegt.

@SteveL-MSFT Das heißt, die Funktion wird für 7.0 vorangetrieben? Wird die Kompatibilität von Variablen unterbrochen, die ? in ihrem Symbol verwenden können?

@TheIncorrigible1 Ja, diese Funktion wird in PS7 weiterentwickelt. Es sollte die Kompatibilität mit der Verwendung des Alias ? beeinträchtigen. Es gibt Bedenken hinsichtlich der Sehschärfe von ? wenn man sich ein Skript ansieht, das versucht, Where-Object und ternary , aber wir werden sehen, was das Benutzerfeedback dazu ist. Im Allgemeinen erwarten wir nicht, dass die meisten Benutzer diesen Operator verwenden, aber das sollte ihn nicht daran hindern, voranzukommen.

@SteveL-MSFT Ich meine Variablen mit dem Namen $isValid? oder ähnlich. Dies sind gültige Token in der aktuellen Iteration von PS.

@TheIncorrigible1 :

Das Anfordern von Leerzeichen zwischen dem ersten Operanden und ? löst dieses Problem, wie zuvor vorgeschlagen, und für mich ist dies eine vollkommen vernünftige Lösung:

  • Das : _auch_ erfordert Leerzeichen, weil so etwas wie $true ? $number:42 nicht funktionieren würde, da $number:42 _als Ganzes_ als einzelne Variablenreferenz interpretiert würde.

  • C# erlaubt zwar true?number:42 , aber ich glaube nicht, dass wir uns um Kompatibilität auf dieser Ebene kümmern müssen oder können. Ich persönlich schätze Prägnanz, aber nicht auf Kosten der Lesbarkeit; selbst wenn ich $true?$number:42 schreiben könnte, würde ich es nicht tun.

(Abwärtskompatibilität wird in der Tat ein Problem sein, wenn (Hinweis, Hinweis) wir nullbedingten Zugriff implementieren. Die Freizügigkeit von PowerShell in Bezug auf Bezeichnernamen ist im Allgemeinen problematisch, wie dieses Schiff ist gesegelt )

Ja, ich denke, es ist sinnvoll, die Whitespace-Anforderung zu belassen. Es ist immerhin knapp genug, wie es ist. 😁

Der Prototyp versuchte ziemlich hart, Zahlen mit ? und : im Kontext des ternären Operators (wo wir wissen, dass wir einen Ausdruck erwarten) anders zu analysieren. Sie können also Dinge wie ${isWindows}?12:47 schreiben.
Zahlen wie 123? oder 1:23 werden heute als generisches Token tokenisiert, was überhaupt nicht nützlich ist, wenn wir wissen, dass wir einen Ausdruck erwarten.

Bei Variablen ändert sich überhaupt nichts daran, wie ? oder : für den Variablennamen verwendet werden können, da Variable ein Ausdruck ist.

Guter Punkt, @daxian-dbw; Ich habe vergessen, dass {...} verwendet werden kann, um jede Mehrdeutigkeit von Variablennamensgrenzen aufzulösen, also denke ich, dass Code-Golfer etwas wie ${isWindows}?${number}:47 könnten

Können wir das jetzt schließen?

Schließen über #10367

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen

Verwandte Themen

JohnLBevan picture JohnLBevan  ·  3Kommentare

andschwa picture andschwa  ·  3Kommentare

pcgeek86 picture pcgeek86  ·  3Kommentare

rkeithhill picture rkeithhill  ·  3Kommentare

ajensenwaud picture ajensenwaud  ·  3Kommentare