Powershell: Erfordert keine { ... } um Variablennamen für den nullbedingten Memberzugriff

Erstellt am 17. Dez. 2019  ·  53Kommentare  ·  Quelle: PowerShell/PowerShell

Folge von #3240.

NULL-bedingter Mitgliederzugriff ( ?. ) wurde implementiert und wird in 7.0 als _experimentelle_ Funktion verfügbar sein

Im Interesse der Abwärtskompatibilität erfordert die Implementierung jedoch derzeit, dass der Variablenname in {...} , da ? technisch gesehen ein zulässiges Zeichen in einem Variablennamen ist, dessen Verwendung überraschenderweise _nicht_ {...} erfordert

Das heißt, wenn Sie einen Versuch ignorieren möchten, $obj.Method() aufzurufen, wenn $obj $null (oder undefiniert) ist, würden Sie analog zu C# Folgendes erwarten:

# Does NOT work as intended.
# 'obj?' as a whole is interpreted as the variable name.
$obj?.Method()

Stattdessen müssen Sie derzeit Folgendes verwenden:

# !! Must enclose 'obj' in {...} to signal that '?' is a syntactic element as part of '?.'
${obj}?.Method()

_Update_: Null-Coalescing - $var??='default und $a??$b - und der ternäre Operator - $var?1:0 - sind ähnlich betroffen (obwohl dort die Verwendung von Leerzeichen vor dem ? löst das Problem).

Diese Anforderung ist (a) unerwartet und (b) umständlich:

  • Neue Benutzer werden nicht erwarten, dass {...} und wissen nicht unbedingt, dass _it_ erforderlich ist, wenn Folgendes fehlschlägt (möglicherweise _unerkannt_, es sei denn, Set-StrictMode -Version 2 oder höher ist wirksam): $o = [pscustomobject] @{ one = 1 }; $o?.one

  • Auch wenn Benutzer _do_ wissen, dass {...} :

    • Sie werden gelegentlich vergessen, es zu verwenden, weil es nicht intuitiv ist.
    • Wenn sie sich erinnern, wird diese scheinbar künstliche Anforderung eine anhaltende Quelle der Frustration sein, zumal {...} schwer zu tippen ist.

Die Verwendung von {...} sollte nicht notwendig sein, und obwohl dies nicht einer _breaking_ Änderung gleichkommt, fällt es wohl in die Kategorie 3: Unwahrscheinliche Grauzone .


Warum diese Änderung als akzeptabel angesehen werden sollte:

Hinweis: @rjmholt erörtert in diesem Kommentar , warum das Ändern der Syntax von PowerShell _im Allgemeinen_ sehr problematisch ist, aber aus den unten aufgeführten Gründen lohnt es sich meiner Meinung nach, hier eine Ausnahme zu machen.

?. ist eine _neue_ syntaktische Funktion; per Definition Skripte, die es verwenden, _nicht_ (sinnvoll) laufen auf älteren Versionen - es sei denn, Sie fügen speziell Bedingungen hinzu, die Legacy-Version-kompatible Codepfade bereitstellen, aber das scheint sich kaum zu lohnen - Sie würden dann einfach bei den Legacy-Funktionen bleiben.

Ja, die Interpretation von $var?.foo in alten Skripten, die $var? als Variablennamen verwendeten, würde nicht funktionieren, aber:

  • ? hätte niemals als Teil eines Bezeichners erlaubt sein dürfen, _ohne ihn in {...} _ einzuschließen.

  • Da dies unerwartet und für viele wahrscheinlich sogar _unbekannt_ ist, sind solche Variablennamen in freier Wildbahn äußerst selten, aus eigener Erfahrung, aber @mburszleys Analyse liefert greifbarere Beweise .

    • Sogar Ruby erlaubt nur ? (und ! ) am _Ende_ von Bezeichnern und dort nur von _Methoden_ Bezeichnern, und ich vermute, dass die meisten Ruby-Benutzer wissen, dass sie _nicht_ davon ausgehen sollten, dass andere Sprachen unterstützen das gleiche.

Also, pragmatisch gesprochen:

  • Der überwiegende Teil des vorhandenen Codes ist davon nicht betroffen – ein Token wie $var?.foo wird einfach nicht gefunden.

  • Wenn Sie $var?.foo mit der neuen Semantik schreiben, dann könnte die Ausführung auf älteren Versionen zu einem anderen Verhalten führen (anstatt auf offensichtliche Weise zu brechen), je nachdem, welcher strikte Modus in Kraft ist - aber _das sollten Sie immer Erzwingen Sie die Mindestversion, die erforderlich ist, um Ihren Code trotzdem wie beabsichtigt auszuführen_ ( #requires -Version , module-manifest keys).

Alles in allem ist dies für mich ein klarer Fall einer Bucket-3-Änderung: eine technisch bahnbrechende Änderung, die sehr wenig bestehenden Code zerstört und gleichzeitig echte Vorteile bietet (oder umgekehrt ständige Kopfschmerzen aufgrund unerwarteten Verhaltens vermeidet).

Committee-Reviewed Issue-Enhancement WG-Language

Hilfreichster Kommentar

@rjmholt , während ich denke , verstehen können , wie schwierig eine solche Änderung _im Prinzip_ ist, spielt es in diesem speziellen Fall _in der Praxis_ keine Rolle, und ich glaube nicht, dass eine PSSA-Regel überhaupt erforderlich ist:

  • Die Analyse von @ThomasNieto hat gezeigt, dass - wenn wir glauben, dass der Korpus repräsentativ für den gesamten PowerShell-Code da draußen ist -, dass _praktisch niemand Variablen mit Namen verwendet, die auf ? _ enden.

  • Wenn ich raten sollte, würden die meisten Leute nicht einmal daran denken, solche Variablennamen zu verwenden, weil sie nicht erwarten würden, dass sie funktionieren (mich eingeschlossen), und wahrscheinlich nicht einmal die Ausnahme bemerken, dass die automatische $? Variable bildet (deren Name in POSIX-kompatiblen Shells wie bash ebenfalls eine Ausnahme ist).

    • Tatsächlich zeigt ein genauerer Blick auf die Analyse von 8 Dateien:

      • 5 enthalten nur _falsche positive Werte_, nämlich Variablen, die innerhalb von _Strings_ verwendet werden, wie "Are you sure you want to kill $vParam?" - tatsächlich sind diese Verwendungen _kaputt_ und zeigen, dass die Skriptautoren _nicht_ erwartet haben, dass ? sein wird Teil des Variablennamens.

      • 2 dieser Dateien sind nicht mehr öffentlich verfügbar.

      • Nur _1_ davon ist eine echte Verwendung von ? -Endvariablen - als _Boolesche_ Variablen (zB $key1? ), die, nebenbei bemerkt, daher _nicht_ mit dem Member-Access-Operator kombiniert werden , . /cc @stevenayers.

Basierend auf dem oben Gesagten erscheint mir dies wie ein Lehrbuch Bucket 3: Unwahrscheinliche Grauzonenänderung, die daher _akzeptabel_ ist - und ich denke, die _Vorteile_ dieser Änderung wurden überzeugend argumentiert.

Die _Dokumentation_ der Verhaltensänderung (mit Begründung) sollte ausreichen.

Natürlich:

  1. Voraussetzung hierfür ist, dass (a) die Analyse korrekt ist und (b) das öffentlich zugängliche Korpus repräsentativ ist.

  2. es steht im krassen Widerspruch zu der Behauptung des Komitees, dass "es ziemlich viel Verwendung von Variablennamen gab, die mit einem Fragezeichen enden" (was natürlich nur ein Problem wäre, wenn solche Variablennamen nicht in {...} ).

Geht man davon aus, dass 1. wahr ist (wir haben nichts für 2. gehört), haben wir zwei Möglichkeiten:

  • Reiß das Pflaster ab und verbiete ? in Variablennamen in Zukunft, es sei denn, es wird in {...} (mit der offensichtlichen Ausnahme von $? ) - das wird das verschwindend kleine brechen Anteil der Skripte, die derzeit darauf angewiesen sind.

    • Das heißt, etwas wie $key1? , auf das weder . noch ein weiteres ? ( $key1??'else' ) noch ein ternärer Ausdruck ( $key1?1:0 ) folgt. würde einen _Parser-Fehler_ verursachen.

      • Wie die Beispiele für null-koaleszierende und ternäre Operatoren zeigen, würden auch sie von dieser Änderung profitieren - derzeit benötigen Sie entweder ein _Leerzeichen_ - $key1 ?1:0 / $key1 ??'else' - oder {...} - ${key1}?1:0 / ${key1}??'else'

    • Innerhalb von _erweiterbaren Strings_ würde ? dann nicht mehr als Teil eines (nicht- {...} -eingeschlossenen) Variablennamens betrachtet, also würden wir tatsächlich vorhandene Skripte _korrigieren_, die irrtümlicherweise Strings wie "Are you sure you want to kill $vParam?" . 😁
  • Wenn wir wirklich der Meinung sind, dass wir vermeiden müssen, den verschwindend kleinen Anteil bestehender Skripte zu brechen, _könnten_ wir die von @ExE-Boss vorgeschlagene Logik in Betracht

Alle 53 Kommentare

Um es klarzustellen, der Meilenstein bedeutet nur, dass das Team ihn basierend auf dem Feedback diskutieren sollte, nicht dass wir uns verpflichtet haben, diese Änderung vorzunehmen.

@mklement0

? sollte niemals als Teil eines Bezeichners erlaubt sein, ohne ihn in {...} einzuschließen.

Ähm - die ursprüngliche Basissprache für PowerShell war die Posix-Shell, die $? für den Exitcode qed '?' ist in Variablennamen ohne Anführungszeichen erlaubt.

es kann (sinnvoll) nicht auf älteren Versionen laufen

Klar kann es:

PS>  $abc?=@{a=1; b=2; c=3}
PS>  $abc?.b                                                                                        1
PS>  2                      

Klar kann es:

Es kann _mit der neuen Semantik_ (null-bedingter Zugriff) nicht sinnvoll ausgeführt werden - das war alles, was ich sagen wollte.

Ja, Ihr Beispiel funktioniert derzeit, aber _mit anderer Semantik_ ( abc? _einschließlich der ? _ als Variablenname) - aber aus den genannten Gründen lohnt es sich, diesen Eckfall aus Gründen der Herstellung aufzugeben ?. funktioniert wie erwartet.

Die ursprüngliche Basissprache für PowerShell war die Posix-Shell, die $? für den Exit-Code verwendet

$? ist eine _Ausnahme_ in POSIX-ähnlichen Shells; Sie können Folgendes _nicht_ tun:

# bash, ksh, zsh, dash (all common /bin/sh implementations)
foo?='bar' # BOOM! E.g. "bash: foo?=bar: command not found"

(Und natürlich verlangt niemand, dass $? in PowerShell abgeschafft wird.)

Und natürlich sollte erwähnt werden, dass _alle anderen_ automatischen Variablen im selben Raum wie $? (dh $^ und $$ ) explizit speziell sind- im Tokenizer eingeschlossen. Und das gilt auch für $? , auch wenn es (derzeit) nicht sein muss.

Es scheint mir klar zu sein, dass zu der Zeit, als der Code geschrieben wurde, erwartet wurde, dass ? kein gültiges Bezeichnerzeichen sein würde.

Ich kenne nur eine Person, die ? am Ende von Variablennamen in ihren Skripten verwendet hat, und das ist @StartAutomating. Da er diese Syntax tatsächlich verwendet hat, hielt ich es für sinnvoll, seine Aufmerksamkeit auf diese Diskussion zu lenken.

Auch @vexx32 , der Grund dafür, dass $? im Tokenizer in Sonderbuchstaben geschrieben wird, liegt darin, dass Sie keine Variable mit einem Namen erstellen können, der mit ? beginnt. zB $??? = 'foo' wird nicht geparst. Variablennamen müssen mit alphanumerischen Zeichen oder einem Unterstrich beginnen und können derzeit alphanumerische Zeichen, Unterstriche oder Fragezeichen enthalten. Ich stimme zu, dass ?. als null-bedingter Memberzugriffsoperator geparst werden sollte, aber ich wollte klarstellen, warum ? im Tokenizer eine Sondergröße hat.

Vielen Dank, dass Sie mich auf diesen Chat aufmerksam gemacht haben.

Für das, was es wert ist, habe ich ein paar Gedanken:

  1. Obwohl diese Variablen selten sind, möchte niemand Whack-a-Mole spielen, wenn Back-Compat seine Skripte bricht
  2. Abgesehen von den zutiefst geekigen Leuten würde ich erwarten, dass ${obj}?.Method() oder $obj?.Method() wenig Aufwärtstrend erfahren werden. Es gibt ein Jahrzehnt an Anleitungen im Web, wie man Nullen verwaltet, und ich sehe nicht, dass viele Leute von if ($obj) { $obj.Method() } _nur um auf den v7-Zug zu kommen_
  3. Außerdem lernen die meisten Leute, die Probleme mit unerwarteten Variablennamen haben, die ${}-Syntax (mit einem Unterstrich hast du sie natürlich schon getroffen). Ich würde erwarten, dass die Überlappung des Venn-Diagramms von "Personen, die diese Funktion verwenden möchten" mit "Personen, die die ${}-Syntax bereits kennen" fast 100 % beträgt.
  4. Da die Syntax nicht so mächtig ist wie ein vollständiger Unterausdruck und vollständige Unterausdrücke sowohl im Kern als auch nicht funktionieren, würde ich erwarten, dass die meisten Leute dies auch in Zukunft verwenden werden.

Wenn man also die Mathematik durchführt, gibt es mehrere konkrete Gründe, dies _nicht_ zu tun, und nur einen vagen Grund, dies zu tun (für einige Benutzer _könnte_ es einfacher sein). Angesichts der geringen Prävalenz von ? in Variablennamen _könnten_ Sie mehr Menschen helfen, als Sie schaden, aber meiner Meinung nach ist es ein Münzwurf.

Angesichts eines solchen Vorteilspotenzials des Münzwurfs werde ich Robert McNamara paraphrasieren: "Wenn wir verdammt sind, wenn wir es tun, und verdammt, wenn wir es nicht tun, werde ich es auswählen, wenn wir es nicht tun".

Ich schlage vor, dass $obj?.Method() standardmäßig als $<var i="6">obj</var> ?. <var i="9">Method</var>() $obj?.Method() funktioniert und nur auf $<var i="11">obj?</var> . zurückfällt <var i="14">Method</var>() wenn $obj nicht im Geltungsbereich vorhanden ist, $obj? jedoch existiert und #requires ‑Version nicht v7+ ist.

@ExE-Boss, das scheint eine Menge Ausnahmen für diese spezielle Regel zu sein.

Ich wiederhole meine Frage nach dem Wert dieser besonderen Regel.

Darüber hinaus stellt sich die Frage: "Was wissen wir noch nicht über die Variablensyntax, die wir brechen könnten?"

Wenn der Konsens darin besteht, die ${...} Syntax dafür zu erzwingen, wäre die Unterstützung für OptionalFeatures hier wünschenswert, damit Leute wie ich, die diese Syntax verwenden (ich werde sie _viel_ verwenden), sich aus dem Rauschen entfernen können .

Da wir hier umschreiben:
"Die Logik schreibt eindeutig vor, dass die Bedürfnisse der Vielen die Bedürfnisse der Wenigen überwiegen." - Spock

Wenn man also die Mathematik durchführt, gibt es mehrere konkrete Gründe, dies _nicht_ zu tun, und nur einen vagen Grund, dies zu tun (für einige Benutzer _könnte_ es einfacher sein).

@StartAutomating : Es gibt mehrere Gründe, und sie sind konkret und nicht vage. Eines der Ziele dabei ist auch die Code-Einfachheit. Variablennamen mit {} funktioniert direkt gegen dieses Ziel.

Ich bin mit @mklement0 und @KirkMunro dabei. Persönlich finde ich die Syntax von ${...}? unnatürlich und unnötig komplex. Wir hatten bereits bahnbrechende Änderungen und in diesem Fall ist es ein kleiner Preis, den Sie im Austausch für Klarheit zahlen müssen.

@StartAutomatisierung

  1. Außerdem lernen die meisten Leute, die Probleme mit unerwarteten Variablennamen haben, die ${}-Syntax ( mit einem Unterstrich würden Sie sie natürlich schon treffen ). Ich würde erwarten, dass die Überlappung des Venn-Diagramms von "Personen, die diese Funktion verwenden möchten" mit "Personen, die die ${}-Syntax bereits kennen" fast 100 % beträgt.

Das hält nicht. Unterstriche sind gültige Zeichen in Variablennamen.

@vexx32

Es scheint mir klar zu sein, dass es zu der Zeit erwartet wurde, als der Code geschrieben wurde

Nö.

Zeichen vertauschen? $foo.?Property sieht nicht kollidierend aus, da Eigenschaftsnamen, die mit Fragezeichen beginnen, bereits in Anführungszeichen gesetzt werden müssen:

PS C:\> $foo = [pscustomobject]@{'?'=1; '?name'=2}
PS C:\> $foo.?name
At line:1 char:6
+ $foo.?name
+      ~
Missing property name after reference operator.
    + CategoryInfo          : ParserError: (:) [], ParentContainsErrorRecordException
    + FullyQualifiedErrorId : MissingPropertyName
PS C:\> $foo.'?name'
2

@HumanEquivalentUnit , leider würde dies zu ewiger Verwirrung mit der seit langem etablierten ?. Syntax führen, die in C# und mehreren anderen Sprachen verwendet wird (auch Sie müssten ein alternatives Formular für den Indexer finden ( ${arr}?[0] ) und etwas wie $arr[0]? würde zu Verwirrung mit dem ternären Operator führen)

Es gibt keine saubere Lösung.

  1. Eine unbekannte Anzahl von Menschen verwenden ? am Ende eines Variablennamens. Obwohl es eine optionale Funktion ist, kann man sagen "Schalten Sie es nicht ein, wenn Sie diese Skripte ausführen", aber die Person, die es ausführt, muss aktuelle und zukünftige Skripte überprüfen, die sie von welcher Quelle auch immer erhalten.
  2. Alternative Syntax ist keine gute Option, da sie etwas nicht sehr Powershelly aus C# importiert
  3. Das Ändern des Verhaltens basierend auf #requires funktioniert nicht außerhalb eines gespeicherten Skripts und schlägt fehl, sobald jemand Code aus einem langen Skript kopiert, ohne das Tag zu setzen.
    4. (dir *.ps2)?.count und (dir *.ps1)?.count zeigen, dass der Operand keine Variable sein muss.
    ($Host)?.toString() / ($null)?.toString() es überflüssig, den Namen in geschweifte Klammern zu setzen. Es sind immer noch zusätzliche Tastenanschläge, aber es ist logischer und weniger hässlich.
  1. Das Ändern des Verhaltens basierend auf #requires funktioniert nicht außerhalb eines gespeicherten Skripts und schlägt fehl, sobald jemand Code aus einem langen Skript kopiert, ohne das Tag zu setzen.

Dies gilt für _jeden_ Code, der Funktionen verwendet, die in früheren Versionen nicht unterstützt wurden.
Wenn dies das vorrangige Anliegen wäre, würde niemals eine neue Sprachfunktion oder ein neuer Cmdlet/Cmdlet-Parameter eingeführt werden.

(Hoffentlich haben Sie in älterem Code mindestens Set-StrictMode -Version 1 in Kraft, in diesem Fall würde $var?.foo laut fehlschlagen, da keine Variable namens var? existiert).

  1. macht es überflüssig, den Namen in geschweifte Klammern zu setzen.

Das Ersetzen von (...) durch {...} ist nur eine marginale Verbesserung.

Welche zusätzliche Syntax auch immer verwendet wird, das Problem hier ist der _Bedarf_ für zusätzliche Syntax – für etwas, das _so wie es ist_ funktionieren sollte – nicht nur für die Eingabekomfort, sondern auch um _vernünftige Erwartungen_ zu erfüllen.

  1. Das Ändern des Verhaltens basierend auf #requires funktioniert nicht außerhalb eines gespeicherten Skripts und schlägt fehl, sobald jemand Code aus einem langen Skript kopiert, ohne das Tag zu setzen.

Dies gilt für _jeden_ Code, der Funktionen verwendet, die in früheren Versionen nicht unterstützt wurden.
Wenn dies das vorrangige Anliegen wäre, würde niemals eine neue Sprachfunktion oder ein neuer Cmdlet/Cmdlet-Parameter eingeführt werden.

Das war nicht ganz das, was ich meinte. Weiter oben wurde vorgeschlagen, dass die Verarbeitung anders sein könnte, wenn #pwsh 7 angegeben ist. Beleuchten Sie ein neues Verhalten nur, wenn Sie #requires setzenist nicht gut.

(Hoffentlich haben Sie in älterem Code mindestens Set-StrictMode -Version 1 in Kraft, in diesem Fall würde $var?.foo laut fehlschlagen, da keine Variable namens var? existiert).

Nach meiner Erfahrung wird Set-Strictmode nicht viel verwendet. Weil (a) davon ausgegangen wird, dass die Standardeinstellung ohne sie "richtig" ist und (b) die Häufigkeit der Verwendung von Dingen, die darauf beruhen, dass sie ausgeschaltet sind, zu hoch ist. Diese Operatoren werden häufig verwendet. In jedem Fall ist das Problem älterer Code, bei dem $var? existiert und hat eine foo-Eigenschaft, aber jetzt sucht der Code nach $var ... Möglicherweise würde die neue Verarbeitung einen Fehler verursachen, WENN strictmode gesetzt ist, weil $var nicht existiert ....

  1. macht es überflüssig, den Namen in geschweifte Klammern zu setzen.

Das Ersetzen von (...) durch {...} ist nur eine marginale Verbesserung.

Jawohl. ($x) ist etwas besser als ${x}, aber nur geringfügig. ( Get-user "Bob")?.disable() ist besser als

$u = get-user "bob" 
($u)?.disable

Welche zusätzliche Syntax auch immer verwendet wird, das Problem hier ist der _Bedarf_ für zusätzliche Syntax – für etwas, das _so wie es ist_ funktionieren sollte – nicht nur für die Eingabekomfort, sondern auch um _vernünftige Erwartungen_ zu erfüllen.

Jawohl.
$var. foo Mit Leerzeichen funktioniert. ${foo} ?.bar() nicht weil ? ist in einem Funktions- oder Aliasnamen erlaubt (?. ist für beide zulässig). Teile der C#-Syntax in vorhandene Syntaxregeln einzubinden, ohne Dinge zu brechen, ist nicht immer praktikabel Manchmal verdient "Dies ist in C# verfügbar ..." wirklich die Antwort "Ja. Sie wissen, wo C# ist, wenn Sie es wollen".
:-)

Um die SemVer- Kompatibilität aufrechtzuerhalten, sollte dies in einer Hauptversion (vorzugsweise 7.0.0 ) erfolgen.

Siehe auch meinen obigen Vorschlag ( https://github.com/PowerShell/PowerShell/issues/11379#issuecomment-566756120 ).

@ExE-Boss Ja, es war Ihr Kommentar, auf den ich mich bezog, als ich sagte, abhängig von #requires könnte es nicht die gute Idee sein, die es zunächst klingt.
Und ja, wenn man bestehende Skripte brechen soll, ist es an der Zeit, wenn sich die Hauptversion ändert, also muss dies schnell erledigt werden oder auf V8 warten

Diese sind noch eine experimentelle Funktion und sind in RC-1 standardmäßig deaktiviert, was meiner Meinung nach für ein Versandprodukt gleich bleiben wird. Dass erlaubt das Verhalten (oder auch sein zweites experimentelles Feature) geändert werden - es sollte auch blockieren / warnen , wenn sie versuchen , eine Variable zu erstellen mit bestimmten Zeichen endet. Wenn ich es aktiviere und dann Skripte mit fehlerhaften Variablennamen verwenden möchte, liegt die Verantwortung bei mir - natürlich bedeutet dies, dass Skripte, die ich herunterlade, die dies tun, nur "kaputt" aussehen, was unter dem Banner "experimentell" erträglicher ist.

Ich bin kein ernsthafter PowerShell-Entwickler; Ich bin auf der Suche nach einer Lösung für einen Fehler hierher gekommen und bin zufällig auf dieses Problem gestoßen. Für die Befehlszeilen-Skripterstellung verwende ich meistens bash. Ich gehöre wahrscheinlich zu der demografischen Gruppe, die Microsoft zu überzeugen versucht, zu PowerShell Core zu wechseln: plattformübergreifender Entwickler, der eine schnelle Skriptsprache benötigt, die weniger schmerzhaft ist als Bash.

Ich habe oft festgestellt, dass viele der Entscheidungen im Zusammenhang mit der Syntax von PowerShell für Leute, die nicht in erster Linie PowerShell-Entwickler sind, nicht intuitiv sind. Als ich PowerShell das letzte Mal für etwas Ernstes verwendet habe, war ich entsetzt über das Fehlen eines Null-Koaleszenz-Operators oder sogar eines ternären Operators, den ich stattdessen verwenden könnte - was dazu führte, dass ich diese beliebte PowerShell-Antwort auf Stack Overflow veröffentlichte . Das war im Jahr 2013, und das ist sicherlich einer der drei wichtigsten Gründe, warum ich PowerShell seitdem meistens gemieden habe. Der springende Punkt einer Skriptsprache ist, dass ich etwas schnelles und schmutziges mit viel Syntaxzucker möchte, keine ausführlichen if-else-Anweisungen.

@StartAutomating sagte:

Abgesehen von den zutiefst geekigen Leuten würde ich erwarten, dass ${obj}?.Method() oder $obj?.Method() wenig Aufwärtstrend erfahren werden. Es gibt ein Jahrzehnt an Anleitungen im Web, wie man Nullen verwaltet, und ich sehe nicht, dass viele Leute von if ($obj) { $obj.Method() } wechseln, nur um auf den v7-Zug zu kommen

Ich bin nur n = 1, aber als Nicht-PowerShell-Entwickler stimme ich nicht zu. Das neue ? Syntax ist etwas, was ich ziemlich schnell herausfinden würde, selbst als jemand, der PowerShell vielleicht einmal alle paar Monate berührt, und es würde definitiv die Chancen erhöhen, dass ich in Zukunft PowerShell anstelle von Alternativen verwende. Wenn ich dann sehe, dass eine verrückte {}-Syntax für die Abwärtskompatibilität erforderlich ist, werde ich mit den Augen rollen und zu dem zurückkehren, was ich bereits verwendet habe.

Ich verstehe die Betonung der Abwärtskompatibilität hier nicht. PowerShell Core hat bereits die meisten meiner vorhandenen Skripts abgebrochen, weil sie Teile von .NET verwendet haben, die nicht in .NET Core enthalten sind. (Ich beschwere mich nicht darüber – .NET Core ist großartig, aber wenn Sie die Abwärtskompatibilität brechen möchten, ist jetzt Ihre Chance.)

Zunächst einmal glaube ich, dass mein erstes Feedback zu Missverständnissen geführt hat.

Meine Vermutung war, dass ${} nicht _so seltsam für PowerShell-Entwickler_ wäre, da sie diese Syntaxform bereits kennen müssten, wenn sie jemals eine Variable mit einem eingebetteten ? oder und Unterstrich in einer Zeichenfolge.

Vielen Dank für die vielen Erinnerungen, dass diese Syntax für Nicht-PowerShell-Entwickler umständlich sein könnte.

Der zweite Teil meines Feedbacks könnte in der Mischung verloren gegangen sein: Da es in PowerShell schon länger andere Alternativen zum Null-Coalescing gibt und diese weit verbreitet sind, weiß ich nicht, wie viel Aufwärtstrend das Feature _bei bestehenden PowerShell-Benutzern_ hätte. Sie wollen reinkommen und sagen: "Das ist das Einzige, was ich brauche, um PowerShell zu verwenden", und ich kann Ihrer Meinung nicht widersprechen (obwohl ich sagen könnte, dass Sie einen Wald an coolen Funktionen vermissen, die nach einem Baum der Sprache suchen Vertrautheit).

Der dritte Teil meines Feedbacks scheint unverhältnismäßig zu sein. Sprechen Sie als einer der Leute, die gelegentlich Variablen namens $IsThisRight verwendet haben? = Test-Etwas , meine erste Reaktion auf die möglichen Neuigkeiten über diese Variableneinschränkung war "Na ja, ich denke, ich muss einige Variablen umbenennen, ich habe sowieso nicht so viel dafür bekommen."

Um zu versuchen, den Thread neu zu formulieren und zu beenden:

  1. IMHO, ${} wird wahrscheinlich keine so seltsame Syntax für _existierende_ PowerShell-Entwickler sein
  2. Sie können diese Funktion gerne für cool halten; Für mich ist es eine Sprachvertrautheits-Gateway-Droge, und ich würde jedem, der diesen Thread liest, wärmstens empfehlen, zu lernen, wie man die Zuweisung von ifs / foreaches / whiles usw.
  3. Als einer der betroffenen Autoren bekomme ich nichts so geschäftskritisches von einem ? am Ende meiner Variablen, dass ich es ablehnen würde, meinen Code zu ändern.

Oder, um es kurz zu machen:

Nehmen Sie diese Änderung vor, wenn Sie möchten. Ich habe ein kleines Pferd in diesem Rennen. Wenn Sie sich dafür entscheiden, übertragen Sie die Änderung bitte deutlich, damit jeder andere, der Variablen mit einem ? entsprechend aktualisieren kann.

Der zweite Teil meines Feedbacks könnte in der Mischung verloren gegangen sein: Da es in PowerShell schon länger andere Alternativen zum Null-Coalescing gibt und diese weit verbreitet sind, weiß ich nicht, wie viel Aufwärtstrend das Feature bei bestehenden PowerShell-Benutzern hätte.

Dem stimme ich auf jeden Fall zu und möchte Ihre Meinung nicht abwerten. Es ist immer schwierig, solche grundlegenden Änderungen vorzunehmen, besonders wenn die Alternative für Leute, die die Sprache bereits intensiv verwenden, intuitiv sein könnte.

Sie wollen reinkommen und sagen: "Das ist das Einzige, was ich brauche, um PowerShell zu verwenden", und ich kann Ihrer Meinung nicht widersprechen (obwohl ich sagen könnte, dass Sie einen Wald an coolen Funktionen vermissen, die nach einem Baum der Sprache suchen Vertrautheit).

Nun, ich hatte das Gefühl, dass die meisten Nicht-PowerShell-Entwickler nicht wirklich an diesen Gesprächen teilnehmen – es ist reiner Zufall, dass ich zufällig darüber gestolpert bin. Meine Verwendung von PowerShell wird sich wahrscheinlich sehr von denen unterscheiden, die Bibliotheken und Open-Source-Tools schreiben. Ich dachte, ich würde nur die Perspektive von jemandem geben, der PowerShell weniger als ausgefallenes Framework verwendet, sondern mehr, um seltsame Aufgaben so schnell wie möglich zu erledigen. Es soll keine anderen Meinungen ablehnen - es ist nur eine andere Meinung aus einer Perspektive, die hier wahrscheinlich nicht allzu oft zu sehen ist.

Eine bessere Nullbehandlung ist nicht das eine, was ich brauche, um PowerShell mehr zu verwenden: es ist das zweite. Die erste war die plattformübergreifende Unterstützung, und ich bin sehr beeindruckt, wie weit das gekommen ist. Persönlich ist Syntax-Zucker für mich eine große Sache, wenn ich eine Sprache für eine bestimmte Aufgabe auswähle: Ich möchte, dass die Syntax meine Arbeit erleichtert. Wenn ich etwas schreibe, das von vielen Leuten gepflegt werden muss, möchte ich wahrscheinlich, dass es ausführlicher ist; aber wenn ich ein schnelles Skript für Verwaltungs- oder Devops-Aufgaben schreibe, möchte ich nur schnell auf Dinge wie null testen.

Der dritte Teil meines Feedbacks scheint unverhältnismäßig zu sein. Sprechen Sie als einer der Leute, die gelegentlich Variablen namens $IsThisRight verwendet haben? = Test-Etwas , meine erste Reaktion auf die möglichen Neuigkeiten über diese Variableneinschränkung war "Na ja, ich denke, ich muss einige Variablen umbenennen, ich habe sowieso nicht so viel dafür bekommen."

Die Bevorzugung der Abwärtskompatibilität ist immer ein faires Argument. In diesem speziellen Fall scheinen jedoch viele PowerShell-Skripte aufgrund des Übergangs zu Core sowieso kurz vor dem Abbruch zu stehen. Wenn die Abwärtskompatibilität regelmäßig unterbrochen wird, ist das frustrierend, aber ich wäre dafür, dass alle wichtigen Änderungen auf einmal passieren, was bedeutet, dass dies wahrscheinlich ein guter Zeitpunkt ist.

In einem Szenario, in dem Sie versuchen, eine ganz neue demografische Zielgruppe anzusprechen – das heißt, nicht auf Windows ausgerichtete Entwickler – müssen möglicherweise einige grundlegende Änderungen vorgenommen werden, um mit dem bereits vorhandenen Markt zu konkurrieren.

Wenn Sie sich dafür entscheiden, übertragen Sie die Änderung bitte deutlich, damit jeder andere, der Variablen mit einem ? entsprechend aktualisieren kann.

Um es klar zu sagen, ich bin damit einverstanden, dass ich mich für die Funktion entscheiden muss - das würde mich nicht davon abhalten, PowerShell zu verwenden. Ich bin bereits daran gewöhnt, eine Reihe von set Befehlen ganz oben in meinen Bash-Skripten zu benötigen. Ich würde es nicht für ideal halten, aber es hätte wenig Einfluss auf meine Entscheidung, PowerShell zu verwenden, solange es gut dokumentiert ist.

Persönlich ist Syntax-Zucker für mich eine große Sache, wenn ich eine Sprache auswähle, um eine bestimmte Aufgabe zu erledigen

Dann sind Sie hier genau richtig! PowerShell ist positiv sacchrin mit syntaktischem Zucker.

Um diejenigen aufzuklären, die es nicht wissen, können Sie in PowerShell auf verschiedene Weise "null coalese":
~$ListWhereNotNull = $null, 1, 2, $null, 3 -ne $null # Dies prüft, ob jedes Element nicht null ist und gibt eine Liste von 1,2,3 . zurück$FirstNonNull = @($null, 1, $null,2 -ne $null)[0] # Dies gibt den ersten Nicht-Null zurück$lastNonNull = @($null, 1, 2, $null -ne $null)[-1] # Dies gibt den letzten Nicht-Null mit einem negativen Index zurück$TheObjectPipelineWay = $null, 1, $null, 2 | Select-Object -Erstes 1$TheAssigningForeachWay = foreach ($item in $null, 1, 2, $null, 3, 4) {if ($item -ne $null) { $item;



Das reicht für den Moment, aber es sollte beweisen, dass die Sprachsyntax viel Flexibilität hat. Alle diese Demos funktionieren bis zurück zu PowerShell 1.0

In diesem speziellen Fall scheinen jedoch viele PowerShell-Skripte aufgrund des Übergangs zu Core sowieso kurz vor dem Abbruch zu stehen.

Darin liegen Sie falsch. Core hat tatsächlich nur sehr wenige Syntax-Break-Änderungen und mehr Module, als Sie denken würden, funktionieren auf Core gut (+- einige Probleme mit Linux vs. Windows-Pfad / Zeilenumbrüchen). Praktischer ausgedrückt ist es weniger wahrscheinlich, dass Ihr Modul auf Core funktioniert, wenn Sie irgendeine Art von Windows-Plattform-spezifischer API-Abhängigkeit haben (zB ich werde nicht den Atem anhalten, um meine WPF-Wrapper unter Linux zum Laufen zu bringen).

Mir geht es so oder so mit der Syntaxänderung immer noch gut: Ich hatte nur das Gefühl, dass zwei der Behauptungen in der neuesten Antwort angesprochen und aufgerufen werden mussten.

Re: Syntaktischer Zucker, mein sarkastischer Verstand zitiert den Film "Snatch": "Ich bin schon süß genug"
Re: Breaking Change Potentials in Core: Wir haben jetzt nur noch wenige, und lasst uns das so gut es geht so bleiben.

@StartAutomating : du damit sagen, dass ich nicht schießen kann? weil für mehr Zucker noch Platz ist denke ich 😜

Um diejenigen aufzuklären, die es nicht wissen, können Sie in PowerShell auf verschiedene Weise "null coalese":

Ich habe das herausgefunden (das ist meine eigene Antwort, die ich geschrieben habe), aber es fühlte sich an wie ein Klumpen. Es ist eine coole Idee mit viel Potenzial, aber wie ein Kommentator dieser Stack Overflow-Antwort darauf hinwies, schließt die Bewertung nicht kurz. Der Operator ?. bedeutet, dass dies beim Verketten von Anrufen/Eigenschaften normalerweise kein Problem mehr ist. Im Jahr 2013 war es jedoch nicht verfügbar – und selbst dann ist in diesen Beispielen eine Menge los, und Sie können in den Kommentaren sehen, wie verwirrend die Leute das fanden. Ich musste genau aufschlüsseln, was diese Beispiele Symbol für Symbol tun.

Darin liegen Sie falsch. Core hat tatsächlich nur sehr wenige Syntax-Break-Änderungen und mehr Module, als Sie denken würden, funktionieren auf Core gut (+- einige Probleme mit Linux vs. Windows-Pfad / Zeilenumbrüchen). Praktischer ausgedrückt ist es weniger wahrscheinlich, dass Ihr Modul auf Core funktioniert, wenn Sie irgendeine Art von Windows-Plattform-spezifischer API-Abhängigkeit haben (zB ich werde nicht den Atem anhalten, um meine WPF-Wrapper unter Linux zum Laufen zu bringen).

Ich spreche in dieser Hinsicht nur aus Erfahrung, anstatt die richtigen Statistiken durchzugehen und zu sammeln. Zum Beispiel könnte ich vor Core ein Passwort mit [System.Web.Security.Membership]::GeneratePassword(32, 6) generieren, aber System.Web ist in Core nicht verfügbar. (Ich weiß, dass ich wahrscheinlich die alte System.Web.dll laden könnte, aber ich würde das lieber nicht tun, wenn ich nicht muss.) Syntaxänderungen sind für mich tatsächlich einfacher zu beheben als fehlende APIs. Das Generieren einer Reihe von Docker-Geheimnissen für ein Devkit scheint ein großartiger Ort zu sein, um ein schnelles Skript zu verwenden, aber es ist in PowerShell Core überraschend ausführlicher als in Bash. Natürlich sehen die Lösungen von bash oft ziemlich hässlich aus.

Re: Syntaktischer Zucker, mein sarkastischer Verstand zitiert den Film "Snatch": "Ich bin schon süß genug"

Es hängt davon ab, ob. Manchmal habe ich das Gefühl, dass PowerShell außergewöhnlich angenehm ist. Der Umgang mit null ist einer der Schlüsselbereiche, in denen ich normalerweise nicht so fühle - obwohl ich das gleiche für viele Sprachen sagen würde. Ich finde auch, dass die traditionelle Inline-PowerShell-if-else-Anweisung im Vergleich zu einem ternären Operator oder der Verkettung von && und || einer Bash umständlich ist. Da dies eines der Hauptprobleme ist, das mich vor Jahren von PowerShell abgetrieben hat, dachte ich, dass es erwähnenswert ist.

Auf der anderen Seite habe ich täglich mit den unterschiedlichsten Sprachen zu tun, und egal was ich schreibe, ich denke immer: "Das wäre in der Sprache X so viel einfacher!" - und dann wann Ich benutze die Sprache X und denke: "Das wäre in der Sprache Y so viel einfacher!" Aber hey, wenn ich die Gelegenheit bekomme, das laut zu sagen und vielleicht die Richtung der Sprache zu beeinflussen, werde ich sie ergreifen.

Ich bin nicht wirklich daran interessiert, meine Meinung hier zu ändern, sondern nur eine andere Perspektive hinzuzufügen.

@StartAutomating :

Ich liebe mich immer etwas neuen Syntaxzucker! Ich wähle Programmiersprachen wie ein Kind, das an Halloween Süßes oder Saures macht.

@Zenexer : Ich mag Powershell wirklich, das tue ich. Ich habe das Glück, PS ausgiebig und täglich bei der Arbeit zu machen. Ich liebe die Flexibilität, besonders die Symbiose mit .NET, oh Mann! Deshalb ist mir seine Richtung wichtig und deshalb ist die Syntax von ${...}? für mich so schwer zu akzeptieren.

Gute Punkte, aber lassen Sie mich ein paar Dinge klarstellen.

Zum Guten oder Schlechten hat PowerShell bisher keine semantische Versionierung verwendet.
Eine neue Hauptversion brachte nur _neue_ Funktionen mit einem eisernen Bekenntnis zur Abwärtskompatibilität.
In Core begannen sich bahnbrechende Änderungen einzuschleichen, teilweise aufgrund der Notwendigkeit, plattformübergreifend zu werden.
Die Hauptversion v7.0 wurde ausgewählt, um eine _Erhöhung_ der Abwärtskompatibilität zu signalisieren: ein Versuch, einen brauchbaren Ersatz für Windows PowerShell bereitzustellen.

Während viele historische Probleme nicht behoben werden können, ohne bestehenden Code ernsthaft zu beschädigen, und daher nur als optionale (Opt-in) Funktionen angeboten werden können,
Bucket 3 Breaking Changes sollten immer eine Option sein: Machen Sie eine Korrektur/Verbesserung, die das _Potenzial_ hat, bestehenden Code zu zerstören, dies aber in der Praxis unwahrscheinlich ist; Alles in allem lohnt es sich, die Sprache zu verbessern.

Wie im OP argumentiert, erscheint mir der vorliegende Fall wie ein Eimer 3 Wechsel; Während wir wissen, dass _einige_ Skripte kaputt gehen ( @StartAutomating wird wissen, wie man seine Skripte repariert), deuten die Daten darauf hin, dass solche Fälle ziemlich selten sind.

Warum ist es selten?

Denn die Verwendung von ? in Variablennamen kommt den meisten Leuten überhaupt nicht in den Sinn, und wenn doch, sollten sie nicht erwarten, dass es _ohne {...} _ funktioniert: {...} , warum sollte es für ? anders sein ?: . , ; ( : kann überhaupt nicht verwendet werden, weil es immer interpretiert wird als ein Laufwerkstrenner)

Namen wie $var? oder $va?r zuzulassen, ohne auch {...} verlangen, war eine Freizügigkeit, die Ärger verlangte, und der Ärger ist gekommen: Er steht der Entwicklung des Sprache, wie in diesem Fall.

Es gibt 3 neue verwandte Funktionen (zumindest in syntaktischer Form), die von C# inspiriert wurden:

  • Ternäre Bedingungen - wird in 7.0 . ein echtes Feature sein

    • (Get-Date).Second % 2 ? 'odd' : 'even'

  • Null-Koaleszenz-Operator - wird in 7.0 . eine echte Funktion sein

    • $var ?? 'default' und $var ??= 'default'

  • Der Null-Bedingungsoperator - das vorliegende Problem - wird in 7.0 ein _experimentelles_ Feature sein

    • $possiblyNull?.ToString()

Alle von ihnen haben ? als Teil ihrer Syntax, und alle sind von der Last des $var? Parsings betroffen, obwohl ?. am offensichtlichsten ist:

  • Während Sie argumentieren könnten, dass etwas wie $var?1:0 nur für Code-Golfer von Interesse ist, würde es gut funktionieren, wenn ? eine syntaktische Funktion hätte - derzeit müssen Sie ein _Leerzeichen_ vor dem ?

  • Im Gegensatz dazu erscheint es mir vernünftig, wenn jemand $var??='bar' (vielleicht weniger $baz = $foo??$bar ) versucht, was derzeit auch ein Leerzeichen erfordert.

Das heißt, wenn wir beim aktuellen Parsing von $var? bleiben, belasten wir _drei_ neue Funktionen (wenn auch in unterschiedlichem Ausmaß), von denen 2 bereits allgemein verfügbar sind (nicht experimentell).

Das Problem bei der Anforderung von {...} ist _nicht_ nur die Unannehmlichkeiten des Tippens: Es geht genauso viel darum, _zunächst nicht zu erwarten, dass es nötig ist_ und später _das Bedürfnis danach zu vergessen_ (mit möglicherweise subtilen Fehlfunktionen) - weil es so kontraintuitiv.

@ExE-Boss, ich stimme @jhoneill zu, dass die Implementierung von

@mklement0 : Es ist unnatürlich/kontraintuitiv/du-name-it. Klammern sind hart, geschweifte Klammern noch härter. In diesem Fall sind sie nicht erforderlich.

@mklement0 da scheint eine Einigung auszubrechen ... Ich denke, das ist eine gute Zusammenfassung.

Ich bin noch nicht vollständig überzeugt, indem ich PowerShell C#-Konstrukte hinzufüge. Wir haben bereits an vielen Stellen Probleme, dass einfach nicht genügend Symbole auf der Tastatur vorhanden sind. Ist ">" "Größer als" oder "weiterleiten zu" ? Ist "=" Zuweisung oder Testgleichheit (verschiedene Sprachen verwenden := für Zuweisen oder == für Gleichheit). Leute, die zwischen Sprachen wechseln, werden vergessen, -eq oder -gt und wir bleiben dabei ... Ist + arithmetische Addition oder String/Array-Verkettung. * ist sowohl Multiplikation als auch ein Platzhalter. % ist Modulo und ein Alias ​​für forEach-object.

Arm ? Ist der Alias ​​für Where-Object. Und ist der Name einer automatischen Variablen. Aber versuchen Sie es mit Get-Alias ? oder Get-Variable ? ... und dann erledigt es die Arbeit eines Platzhalters.

Machen Sie Get-PSdrive und Sie sehen, dass "Variable" usw. kein ":" am Ende des Namens hat. Wenn Sie ein : an einen Namen anhängen, wird er als Laufwerk behandelt. Es sei denn natürlich, Sie haben "$drive="C" und folgen ihm mit "$drive:temp" Jeder, der neu in PowerShell ist (und einige alte Hasen, wenn sie nicht darüber nachdenken) werden verblüfft sein, wenn sie wissen, dass sie es sind. Ich habe gerade einen benannten Bereich "Laufwerk" erfunden.

Dagegen könnte man sagen: 'Erstellen Sie eine neue Syntax mit weiteren Verwendungen für ":" und "?" bist du verrückt?'
IIRC, auf Twitter @BrucePay beschrieb den ternären Operator als "Nicht sehr PowerShelly" und ich neige dazu, zuzustimmen. Aber die "Make it more like C#"-Stimmen haben den Tag gewonnen...

Die meisten Leute würden $PSEdition.length -gt 2 schreiben
aber $PSEdition. length-gt2 funktioniert auch (man kann sogar einen Zeilenumbruch zwischen den beiden Hälften machen.) "." ist auch überladen und dient als "aktuelles Verzeichnis", "in diesem Bereich ausführen" und "Mitglied". In PS V1-V5 fallen mir jedoch keine Operatoren ein, die ein führendes Leerzeichen
$host.debuggerEnabled?0:1 ist in Ordnung, weil "?" angenommen, _nicht_ Teil einer Immobilie zu sein
$IsCoreCLR?0:1 ist nicht weil "?" wird als Teil des Variablennamens angenommen.

Das gleiche gilt für die Null-Koaleszenzoperatoren
$null?? "default" braucht ein Leerzeichen $true.length?? "default" braucht kein Leerzeichen.

Legen Sie den ursprünglichen Anwendungsfall am Anfang der Ausgabe für einen Moment beiseite. Die obigen Fälle zeigen, dass etwas nicht ganz funktioniert. Es wäre behoben, wenn Variablennamen "?" müssen wie Namen mit "." in Klammern gesetzt werden. oder "+" oder ":" und @StartAutomating wer ist ein

Ich denke, es gibt ein kurzes Zeitfenster , um eine experimentelle Funktion einzubauen, die erfordert ? in Namen geschweift werden, und wenn diese Funktion eingeschaltet ist - was sollte die Standardeinstellung sein - alles neu? Operatoren sollten entsprechend parsen. Nur wenn diese Funktion deaktiviert ist, benötigt der Parser Leerzeichen oder geschweifte Klammern mit diesen Operatoren ?.tostring() ist der erste Fehler in einem Skript, daher sollten die Skripte fehlschlagen und nicht gefährlich ausgeführt werden). und idealerweise sollte das nicht mit einem Point-Release passieren (Sie haben Recht, dass PowerShell nicht wirklich sem-ver verwendet, aber es ist immer noch ein gutes Prinzip)

Das Problem bei der Anforderung von {...} ist nicht nur die Unannehmlichkeit des Tippens: Es geht genauso darum, dass man die Notwendigkeit nicht erwartet und später die Notwendigkeit dafür vergisst (mit möglicherweise subtilen Fehlfunktionen) - weil es also kontraintuitiv.

Dies ist ein guter Punkt und würde mich in der Praxis hauptsächlich über ${...?} ärgern. Selbst wenn ich weiß, dass ich {} , besteht die große Chance, dass ich es irgendwann vergesse, und das kann zu subtilen Fehlern führen, die zunächst nicht offensichtlich sind, da es wahrscheinlich immer noch syntaktisch gültig ist. $var??='bar' ist ein gutes Beispiel dafür, obwohl ich normalerweise ziemlich vorsichtig mit den Abständen bin.

Danke, @jhoneill , das ist eine schöne Illustration dafür, wie viele Symbole in PowerShell viel doppelte (dreifache, ...) Pflicht erfüllen.
Wenn Sie alle Verwendungen kennen, ist dies in den meisten Fällen aus folgenden Gründen kein Problem:

  • verschiedene Kontexte (z. B. * als Operator vs. * als Platzhalterzeichen.)

    • Die verschiedenen Kontexte für ? haben auf einer bestimmten Abstraktionsebene tatsächlich etwas gemeinsam: Sie können sich ? in Get-ChildItem | ? Target , $var?.Target , $? vorstellen $var ?? 'none' als alle beinhalten eine Art _Frage_ und damit _Test_ oder _bedingtes Verhalten_.

  • sinnvolles polymorphes Verhalten (zB + Verkettung mit String durchführen).

Ein problematisches Beispiel ist & (Aufrufoperator vs. Hintergrundoperator), der im gleichen Kontext mit unterschiedlicher Semantik verwendet wird, nur abhängig von seiner _Position_.

Es wäre behoben, wenn Variablennamen "?" müssen wie Namen mit "." in Klammern gesetzt werden. oder "+" oder ":"

In der Tat, und das muss wiederholt werden: Die Möglichkeit, ? in Variablennamen zu verwenden, wird nicht verschwinden - aber Sie müssen in Zukunft {...} : ${var?} = @{ foo=1 }; ${var?}?.foo

Wie Sie demonstrieren, erwartet jemand vernünftigerweise _nicht_, dass ? ein gültiges Zeichen ist. . für Dot-Sourcing ist die berechtigte Ausnahme; ? als Where-Object -Alias, der ein Leerzeichen erfordert, mag überraschend sein (zB gci|?target funktioniert nicht), aber Befehlsnamen _do_ müssen mit Leerzeichen von ihren Argumenten getrennt werden).

Leerzeichen zwischen . und einem Mitgliedsnamen ( $obj. foo ) einfügen zu können, ist vor allem in mehrzeiligen Anweisungen sinnvoll, obwohl die wohl lesbarere Form - aus anderen Sprachen bekannt - ist (auch) Erlaube Leerzeichen _vor_ dem . :

# This does NOT work - the . must be *immediately after* the expression / member
(Get-Date)
  .ToUniversalTime()  
  .TimeOfDay

Dies würde die kürzlich hinzugefügte Möglichkeit widerspiegeln, | in die _next_-Zeile zu setzen:

 # Already works in PS Core
Get-Date
  | % ToUniversalTime
  | % TimeOfDay

Dies würde jedoch unauflösbare Mehrdeutigkeiten mit . als Dot-Sourcing-Operator und Befehlsnamen einführen, die mit . - wie unwahrscheinlich. (z. B. . foo in einer neuen Zeile könnte ein Eigenschaftszugriff oder ein Befehl sein, der eine Funktion oder ein Skript namens foo (was in $env:PATH müsste) ; .foo könnte der Name eines _Befehls_ sein).

Der mehrzeilige Fortsetzungs-RFC von @KirkMunro, der sich darauf konzentriert, _commands_ mehrere Zeilen zu überspannen, würde uns die nächstbeste Lösung bieten - siehe https://github.com/PowerShell/PowerShell-RFC/pull/179#issuecomment -498734875.

Wie für die experimentelle Funktion standardmäßig aktiviert sein: Zum Glück _preview_ Releases - aber nicht Release Candidates - jetzt _all_ experimentellen Funktionen standardmäßig drehen; Beachten Sie jedoch, dass dies dauerhaft überschrieben wird, wenn Sie Enable-ExperimentalFeature entweder _ohne_ -Scope oder mit -Scope CurrentUser mit den dort aktivierten Funktionen ausgeführt haben.

@mklement0 Obwohl ich im Grunde all dem zustimme, befürchte ich, dass wir diese spezielle Diskussion mit den zusätzlichen Kleinigkeiten, die Sie dort haben, ein wenig entgleisen könnten; Wenn Sie die Zeilenfortsetzung um den Punkt-Eigenschaftsoperator herum ansprechen möchten, möchten Sie vielleicht eine neue Ausgabe dafür eröffnen, falls es noch keine gibt. 🙂

Ich stimme zu, dass es für Benutzer bestenfalls extrem verwirrend ist, ? als normales Zeichen für Variablennamen zuzulassen, da die Verwendung des Zeichens plötzlich Leerzeichen empfindlich macht, und ich glaube zumindest historisch gesehen nicht, dass Variablennamen _ever_ haben. war in der Vergangenheit Leerzeichen-empfindlich.

Die Einführung dieser Mehrdeutigkeit ist meiner Meinung nach ein größeres Problem, als eine grundlegende Änderung vorzunehmen und ? Verwendung in einem Variablennamen zu verbieten. Mit der Breaking Change können wir ganz einfach eine PSSA-Regel erstellen, um Autoren zu warnen, dass die Syntax nicht mehr zulässig ist. Das Umgekehrte ist jedoch nicht so leicht wahr, und im Gegensatz zum Breaking Change wird es nicht unbedingt zu einem Fehler kommen; Es kann sehr leicht dazu führen, dass Benutzer versehentlich auf die falsche Variable verweisen, ohne zu wissen, was sie tun.

@PowerShell/powershell-committee diskutierte dies, wir hatten den PowerShell-Korpus von Skripten analysiert und es wurden ziemlich viele Variablennamen verwendet, die mit einem Fragezeichen enden. Daher können wir diese Leute und geschweiften Klammern um PowerShell-Variablennamen nicht brechen.

Wir hatten den PowerShell-Korpus von Skripten analysiert und es gab ziemlich viel Verwendung von Variablennamen, die mit einem Fragezeichen enden

Danke, @SteveL-MSFT - können Sie bitte die Ergebnisse dieser Analyse teilen?

Ja, ich wäre neugierig, einiges davon zu sehen, da ich mir bewusst bin, dass einige Community-Mitglieder ihre eigene Analyse durchgeführt haben und nicht annähernd an ein solches Ergebnis gekommen sind.

Ich würde auch gerne die Ergebnisse und die verwendete Methode sehen. Ich habe gestern Abend meine eigene Analyse des

Ich habe 11 eindeutige Variablennamen in 8 Dateien gefunden, die mit einem Fragezeichen enden (außer $?, das 8846 Mal auftauchte). Es gab insgesamt 1.895.983 eindeutige Variablen in 408.423 Dateien. Das bedeutet, dass 0,0006% aller eindeutigen PowerShell-Variablen im Korpus einen Variablennamen haben, der mit einem Fragezeichen endet.

Hier sind die 8 Dateien und 11 eindeutigen Variablen:

File                 : C:\Temp\PowerShellCorpus\Github\alanrenouf_PowerActions\Kill-VM.ps1
QuestionMarkVars     : vParam?
QuestionMarkVarCount : 1

File                 : C:\Temp\PowerShellCorpus\Github\anthonywlee_PowerShell\Send_Notification.ps1
QuestionMarkVars     : To?
QuestionMarkVarCount : 1

File                 : C:\Temp\PowerShellCorpus\Github\aspear_My-PowerCLI-scripts\my-labotomize-vms.ps1
QuestionMarkVars     : vParam?
QuestionMarkVarCount : 1

File                 : C:\Temp\PowerShellCorpus\Github\jlundstrom_Scripts\Powershell\7Zip SFX Creator\Build.ps1
QuestionMarkVars     : Title?
QuestionMarkVarCount : 1

File                 : C:\Temp\PowerShellCorpus\Github\pslaughter_Working\Setup-Host.ps1
QuestionMarkVars     : HostIp?
QuestionMarkVarCount : 1

File                 : C:\Temp\PowerShellCorpus\Github\stevenayers_PowerShell-Scripts\Random Functions\Add-OutlookConferenceRegionNumber.ps1
QuestionMarkVars     : {key1?, key2?, key3?, key4?}
QuestionMarkVarCount : 4

File                 : C:\Temp\PowerShellCorpus\Github\unixboy_powershell-stufff\stopvm.ps1
QuestionMarkVars     : vParam?
QuestionMarkVarCount : 1

File                 : C:\Temp\PowerShellCorpus\PowerShellGallery\PsHg\0.6.2\PsHg.psm1
QuestionMarkVars     : PsHg?
QuestionMarkVarCount : 1

Dies ist das Skript, das zum Generieren des Berichts verwendet wird:

Get-ChildItem -Path C:\Temp\PowerShellCorpus -Include *.ps1, *.psm1 -File -Recurse | ForEach-Object -Parallel {
    try {
        $content = $PSItem | Get-Content

        $ast = [System.Management.Automation.Language.Parser]::ParseInput($content, [ref]$null, [ref]$null)
        $variables = $ast.FindAll({$args[0] -is [System.Management.Automation.Language.VariableExpressionAst ]}, $true)

        # First query because I forgot to exclude $? variables
        # $nonQuestionMark = $variables | Where-Object VariablePath -notmatch '\?$' | Select-Object -Unique
        # $QuestionMark = $variables | Where-Object VariablePath -match '\?$' | Select-Object -Unique

        $nonQuestionMark = $variables |
        Where-Object VariablePath -notmatch '\?$' |
        ForEach-Object { $_.VariablePath.UserPath.ToString() } |
        Select-Object -Unique

        $QuestionMark = $variables |
        Where-Object { $_.VariablePath -match '\?$' -and $_.VariablePath.UserPath -ne '?' } |
        ForEach-Object { $_.VariablePath.UserPath.ToString() } |
        Select-Object -Unique

        $output = [pscustomobject]@{
            File = $PSItem
            QuestionMarkVars = $QuestionMark
            QuestionMarkVarCount = $QuestionMark.Count
            NonQuestionMarkVars = $nonQuestionMark
            NonQuestionMarkVarCount = $nonQuestionMark.Count
        }

        $output
    }
    catch {
        throw
    }
}

Lassen Sie mich wissen, wenn es Probleme mit der Methode gibt, mit der dieser Bericht erstellt wurde. Hier ist ein Beispielskript zum Testen des Audits.

$abc = 'test'
$isAwesome? = $true
$?

$test = {
    $?
    $isabc? = { $adce? = 'test' }
    ${def?} = 123
    ${is a bad var name?} = $isabc?
}

Ergebnisse in:

File                    : C:\temp\variable.ps1
QuestionMarkVars        : {isAwesome?, isabc?, adce?, def?, is a bad var name?}
QuestionMarkVarCount    : 5
NonQuestionMarkVars     : {abc, true, test}
NonQuestionMarkVarCount : 3

Wie es im Matheunterricht heißt: "Bitte zeig deine Arbeit" 😄

Ausgezeichnete Detektivarbeit, @ThomasNieto - danke.

Ich denke, Sie können möglicherweise noch mehr Fälle eliminieren, da die Form ${...} mit der vorgeschlagenen Änderung weiterhin funktioniert - z. B. müssen wir uns nur um $isAwesome? kümmern, nicht um ${isAwesome?}

Mit deiner Beispieldatei:

$variables.Extent.Text.Where({ $_ -match '(?<!\$)\?$' }) | Select-Object -Unique

wir bekommen nur:

$isAwesome?
$isabc?
$adce?

Das heißt, ${def?} und ${is a bad var name?} müssen nicht berücksichtigt werden.

PS: Es ist wahrscheinlich auch besser, $PSItem | Get-Content -Raw zu verwenden, um das gesamte Skript als einen einzigen String zu lesen.

@mklement0 Das ist richtig, ich habe diese Fälle direkt vor dem Posten hinzugefügt, um sicherzustellen, dass das Skript Variablen mit der geschweiften Klammernotation nicht ausschließt.

Nach dem Aktualisieren des Skripts mit Ihren Empfehlungen erzeugt die Testdatei wie erwartet die folgende Ausgabe.

File                    : C:\temp\variable.ps1
QuestionMarkVars        : {isAwesome?, isabc?, adce?}
QuestionMarkVarCount    : 3
NonQuestionMarkVars     : {abc, true, test}
NonQuestionMarkVarCount : 3

Ich habe das aktualisierte Skript für diese 8 Dateien ausgeführt und keine davon verwendet die Notation mit geschweiften Klammern, so dass das Ergebnis immer noch 11 eindeutige Variablen sind, die von der vorgeschlagenen Änderung betroffen sind.

Aktualisiertes Skript:

Get-ChildItem -Path C:\Temp\PowerShellCorpus -Include *.ps1, *.psm1 -File -Recurse | ForEach-Object -Parallel {
    try {
        $content = $PSItem | Get-Content -Raw

        $ast = [System.Management.Automation.Language.Parser]::ParseInput($content, [ref]$null, [ref]$null)
        $variables = $ast.FindAll({$args[0] -is [System.Management.Automation.Language.VariableExpressionAst ]}, $true)

        $nonQuestionMark = $variables |
        Where-Object VariablePath -notmatch '\?$' |
        ForEach-Object { $_.VariablePath.UserPath.ToString() } |
        Select-Object -Unique

        $QuestionMark = $variables |
        Where-Object { $_.VariablePath -match '\?$' -and $_.VariablePath.UserPath -ne '?' -and $_.Extent.Text -match '(?<!\$)\?$' } |
        ForEach-Object { $_.VariablePath.UserPath.ToString() } |
        Select-Object -Unique

        $output = [pscustomobject]@{
            File = $PSItem
            QuestionMarkVars = $QuestionMark
            QuestionMarkVarCount = $QuestionMark.Count
            NonQuestionMarkVars = $nonQuestionMark
            NonQuestionMarkVarCount = $nonQuestionMark.Count
        }

        $output
    }
    catch {
        throw
    }
}

Danke, @ThomasNieto - ich hatte gehofft, wir könnten den Prozentsatz auf 0,0005%

Der Ausschuss muss also einen anderen verwendet haben - privat? - Korpus.

Es stellt sich also neben der Entscheidung über das vorliegende Thema die Frage: Braucht der

@SteveL-MSFT, können Sie das bitte klären?

@mklement0 Ich habe aufgerundet, wenn du dich also nur ein bisschen besser fühlen willst, sind es tatsächlich 0,00058%

In https://github.com/PowerShell/PowerShell-RFC/pull/223#discussion_r318340339 führte @adityapatwardhan eine Analyse mit demselben öffentlichen Korpus durch, den ich verwendet habe, und ergab 62% mit Variablen, die mit einem Fragezeichen enden. Ich habe keine Antwort darauf gesehen, wie er auf diesen Prozentsatz gekommen ist. Hat der PS-Ausschuss diese Analyse verwendet, um diesen Antrag zu bestimmen?

Wenn ich mir den verlinkten Kommentar ansehe , denke ich, was ? in ihrem Namen haben_ 62% ein ? als _letztes_ Zeichen des Namens haben.

Im Gegensatz dazu scheint Ihre Analyse der tatsächlichen Prävalenz von Variablen mit der Endung (ohne geschweifte Klammern) auf ? (als Prozentsatz der Variablennutzung insgesamt) viel relevanter zu sein.

An dieser Stelle hört es sich so an, als würde der Ausschuss nur sagen "Wir wollen nicht" und wenn das der Fall ist, warum überhaupt diese Funktion haben, wenn sie dadurch klobig und unbenutzt sein wird?

@ThomasNieto habe ich auch irgendwo eine Analyse zu diesen Themen durchgeführt und bin zu ähnlichen Ergebnissen wie Ihnen gekommen.

@mburszley Vielen Dank für Ihre Analyse. Ich wollte eine andere Methode (ast vs. regex) verwenden, um die Ergebnisse des letzten Jahres zu bestätigen.

Ich höre dich, @mburszley , aber re:

der Ausschuss sagt nur "Wir wollen nicht"

Wenn dies wirklich eine _Fiat_-Entscheidung wäre – eine, die nicht auf der Analyse der realen Nutzung beruht – würde dies für die Gemeinschaft insgesamt nichts Gutes verheißen, insbesondere angesichts der Tatsache, dass der _angegebene_ Grund eine Grundlage für eine solche Analyse war.

Daher sollten wir dem Ausschuss die Möglichkeit geben, die reale Nutzungsanalyse zu zeigen, auf der die Entscheidung beruhte - oder zu erkennen, dass die Analyse zu kurz war, und die Entscheidung zu überdenken.

Was ist mit meinem Vorschlag in https://github.com/PowerShell/PowerShell/issues/11379#issuecomment-566756120 ?

Ich schlage vor, dass $obj?.Method() standardmäßig als $<var i="9">obj</var> ?. <var i="12">Method</var>() $obj?.Method() funktioniert und nur auf $<var i="14">obj?</var> . zurückfällt <var i="17">Method</var>() wenn $<var i="19">obj</var> nicht im Geltungsbereich vorhanden ist, $<var i="21">obj?</var> jedoch existiert und #requires ‑Version nicht v7+ ist.

Ich würde erwarten, dass es die meisten der Abwärtskompatibilitätsprobleme anspricht.

@ThomasNieto

@mklement0 ist richtig, ich meinte, dass unter den Variablen, die ? , 62% es am Ende verwenden.

Aus den hier im Kommentar gezeigten Ergebnissen scheint es, dass alle Variablen, die ? verwenden, es am Ende verwenden. Daher der Vorschlag, eine nicht brechende Änderung vorzunehmen.

Wenn die Anforderung für {..} entfernt wird, wird das Skript immer noch parsen, aber die Semantik wird anders sein, was meiner Meinung nach sehr gefährlich ist.

Sicher ... aber die Analyse zeigt, dass buchstäblich fast niemand sie verwendet.

Wie jede andere Breaking Change kann sie angekündigt, als experimentelles Feature für eine Weile eingeführt und dann dokumentiert und in den Stall gebracht werden.

Ich sehe keinen Grund, eine esoterische Syntax zu empfehlen, wenn ? als Bezeichner in einer entfernt signifikanten Anzahl von Fällen nicht tatsächlich verwendet wird.

Wenn die Anforderung für {..} entfernt wird, wird das Skript immer noch parsen, aber die Semantik wird anders sein, was meiner Meinung nach sehr gefährlich ist.

Machen Sie sich nicht auch Sorgen, dass Leute, die ?. wie sie es in C/C++/C# tun, die falschen Ergebnisse erhalten, ohne darauf hinzuweisen, dass sie etwas falsch gemacht haben? Zum Beispiel:

PS> $res = "My length is 15"
PS> $res?.Length
0

Sicher, der strikte Modus wird dies finden, aber ich weiß nicht, dass viele Leute den strikten Modus verwenden. Um zu verhindern, dass ein sehr kleiner Prozentsatz von Skripten kaputt geht, scheinen wir viele Leute mit ?. auf Fehler vorzubereiten. Ich bin nicht verrückt nach dem Kompromiss. Trotzdem verstehe ich definitiv den Wunsch, es zu vermeiden, Leute zu brechen, auch wenn es sich um eine sehr kleine Anzahl von Leuten handelt.

Vielleicht benötigt PowerShell ein Äquivalent von Enable-ExperimentalFeature nennen Sie es Enable-PSFeature , für Funktionen, die sich nicht mehr im experimentellen Zustand befinden, aber nicht standardmäßig aktiviert werden können . Für Skripte, die mit Code wie diesem $?.GetType() , könnten Sie Warnungen ausgeben, dass dies in Zukunft nicht mehr funktioniert und Sie stattdessen ${?}.GetType() verwenden sollten. Einzelne Skripte könnten die Funktion mit einem #requires -version 7.1 -feature PSNullConditionalOperators aktivieren. Dann könnte die Funktion möglicherweise bei jedem Treffer von PS 8 standardmäßig aktiviert werden.

Das Beispiel von
Vergessen Sie für einen Moment, was Sie heute über die Funktionsweise von PowerShell wissen. Wenn du siehst

PS> $res?.Length

Es sieht aus wie _name, operator, name_ - was es natürlich ist.
Was wäre sinnvoller: _"?" ist Teil des Operators_ , oder _"?" ist Teil des Vornamens-element_ ?
Wenn diese Operatoren benötigt werden (und ich denke, sie sind "nicht PowerShelly"), haben Sie die Wahl zwischen etwas, das falsch verwendet wird, und einem kleinen Bruch.

Ich würde _jetzt_ damit beginnen, Regeln in psScriptAnalyzer einzugeben, um zu sagen, dass es ein schlechter Stil ist, bestimmte [legale] Zeichen in Variablennamen zu verwenden.

Ich mag Enable-feature . Jemand fügt es in ein Skript ein, um etwas zum Laufen zu bringen, das er verwenden möchte, und ein altes Skript bricht ab, wenn es nach dem neuen Skript ausgeführt wird (aber funktioniert die restliche Zeit). Ich habe gesehen, dass _Drittanbieter-Skript X nach der Ausführung von Skript Y_ fehlschlägt, weil Y den strikten Modus aktiviert und X darauf angewiesen ist, dass es deaktiviert ist; die Autoren beider Drehbücher sind in meinen schlechten Büchern.

Ich würde jetzt anfangen, Regeln in psScriptAnalyzer einzugeben, um zu sagen, dass es ein schlechter Stil ist, bestimmte [legale] Zeichen in Variablennamen zu verwenden.

Hier ist das Problem: Wenn Sie die Tokenisierung von Variablen durch PowerShell ändern, sieht PSScriptAnalyzer sie auch anders. Wenn Sie eine Variable wie $res? , sehen Sie sich Folgendes an:

{
$res?.Length
}.Ast.EndBlock.Statements[0].PipelineElements[0].Expression.Expression.VariablePath.UserPath

gibt Ihnen

res?

ABER, wenn Sie die Art und Weise ändern, wie PowerShell in beispielsweise 7.2 geparst wird, erhalten Sie


Jetzt kann PSScriptAnalyzer ? nicht sehen, weil es nicht mehr Teil des Variablennamens ist (per Definition, da es die Änderung ist, auf die wir testen wollen). Dies liegt daran, dass PSScriptAnalyzer ein PowerShell-Modul ist und denselben Parser wiederverwendet, der in PowerShell ausgeliefert wird. (Und es wäre völlig unhaltbar und ein Rezept für eine Katastrophe, wenn es versucht würde, es neu zu implementieren).

Es gibt Möglichkeiten, dies zu umgehen, wie zum Beispiel das bedingte Kompilieren von PSScriptAnalyzer (und das Versenden einer ganz neuen Assembly), um die neue 7.2-Logik zu testen, um dieselbe Diagnose zu liefern. Aber dann haben Sie überall die Komplexität erhöht (oder alternativ Ihre Testoberfläche verringert), um ein etwas kosmetisches Szenario zu bedienen.

Schlimmer noch, all die anderen Tools da draußen, die ebenfalls auf AST angewiesen sind, haben nicht die Kapazität, diese Art von Komplexität aufrechtzuerhalten, selbst wenn PSScriptAnalyzer dies tut. Die meisten Leute, die AST-Targeting-Tools entwickeln, werden nicht gegen einzelne Nebenversionen von PowerShell kompilieren, um perfekte Korrektheit zu erzielen. Sie werden wahrscheinlich nicht einmal von einer so kleinen Breaking Change wissen, zumal es in keiner Version ein Fehler ist; Es ist die heimtückischste Form des Breaking Change, bei der ein Verhalten leise zu einem anderen wird.

Das ist im Grunde das, was Änderungen auf Parser-/Tokeniser-Ebene wie diese gefährlicher macht. Sogar PSScriptAnalyzer muss sich nach hinten beugen, um sie korrekt zu bedienen, was bedeutet, dass sie gegen solche lästigen Änderungen abgewogen werden müssen.

@rjmholt , während ich denke , verstehen können , wie schwierig eine solche Änderung _im Prinzip_ ist, spielt es in diesem speziellen Fall _in der Praxis_ keine Rolle, und ich glaube nicht, dass eine PSSA-Regel überhaupt erforderlich ist:

  • Die Analyse von @ThomasNieto hat gezeigt, dass - wenn wir glauben, dass der Korpus repräsentativ für den gesamten PowerShell-Code da draußen ist -, dass _praktisch niemand Variablen mit Namen verwendet, die auf ? _ enden.

  • Wenn ich raten sollte, würden die meisten Leute nicht einmal daran denken, solche Variablennamen zu verwenden, weil sie nicht erwarten würden, dass sie funktionieren (mich eingeschlossen), und wahrscheinlich nicht einmal die Ausnahme bemerken, dass die automatische $? Variable bildet (deren Name in POSIX-kompatiblen Shells wie bash ebenfalls eine Ausnahme ist).

    • Tatsächlich zeigt ein genauerer Blick auf die Analyse von 8 Dateien:

      • 5 enthalten nur _falsche positive Werte_, nämlich Variablen, die innerhalb von _Strings_ verwendet werden, wie "Are you sure you want to kill $vParam?" - tatsächlich sind diese Verwendungen _kaputt_ und zeigen, dass die Skriptautoren _nicht_ erwartet haben, dass ? sein wird Teil des Variablennamens.

      • 2 dieser Dateien sind nicht mehr öffentlich verfügbar.

      • Nur _1_ davon ist eine echte Verwendung von ? -Endvariablen - als _Boolesche_ Variablen (zB $key1? ), die, nebenbei bemerkt, daher _nicht_ mit dem Member-Access-Operator kombiniert werden , . /cc @stevenayers.

Basierend auf dem oben Gesagten erscheint mir dies wie ein Lehrbuch Bucket 3: Unwahrscheinliche Grauzonenänderung, die daher _akzeptabel_ ist - und ich denke, die _Vorteile_ dieser Änderung wurden überzeugend argumentiert.

Die _Dokumentation_ der Verhaltensänderung (mit Begründung) sollte ausreichen.

Natürlich:

  1. Voraussetzung hierfür ist, dass (a) die Analyse korrekt ist und (b) das öffentlich zugängliche Korpus repräsentativ ist.

  2. es steht im krassen Widerspruch zu der Behauptung des Komitees, dass "es ziemlich viel Verwendung von Variablennamen gab, die mit einem Fragezeichen enden" (was natürlich nur ein Problem wäre, wenn solche Variablennamen nicht in {...} ).

Geht man davon aus, dass 1. wahr ist (wir haben nichts für 2. gehört), haben wir zwei Möglichkeiten:

  • Reiß das Pflaster ab und verbiete ? in Variablennamen in Zukunft, es sei denn, es wird in {...} (mit der offensichtlichen Ausnahme von $? ) - das wird das verschwindend kleine brechen Anteil der Skripte, die derzeit darauf angewiesen sind.

    • Das heißt, etwas wie $key1? , auf das weder . noch ein weiteres ? ( $key1??'else' ) noch ein ternärer Ausdruck ( $key1?1:0 ) folgt. würde einen _Parser-Fehler_ verursachen.

      • Wie die Beispiele für null-koaleszierende und ternäre Operatoren zeigen, würden auch sie von dieser Änderung profitieren - derzeit benötigen Sie entweder ein _Leerzeichen_ - $key1 ?1:0 / $key1 ??'else' - oder {...} - ${key1}?1:0 / ${key1}??'else'

    • Innerhalb von _erweiterbaren Strings_ würde ? dann nicht mehr als Teil eines (nicht- {...} -eingeschlossenen) Variablennamens betrachtet, also würden wir tatsächlich vorhandene Skripte _korrigieren_, die irrtümlicherweise Strings wie "Are you sure you want to kill $vParam?" . 😁
  • Wenn wir wirklich der Meinung sind, dass wir vermeiden müssen, den verschwindend kleinen Anteil bestehender Skripte zu brechen, _könnten_ wir die von @ExE-Boss vorgeschlagene Logik in Betracht

@SteveL-MSFT

Vielen Dank, dass Sie dieses Thema im September-Community-Call (https://aka.ms/PSCommunityCall) besprochen haben. bis zum nächsten Anruf), ab 46:00 Uhr, basierend auf dem Vorschlag von @ThomasNieto in der vorherigen Aufforderung zu Diskussionsthemen unter https://github.com/PowerShell/PowerShell-RFC/issues/260 :

(Ich hatte gehofft, einen direkten Link zum relevanten Teil der Aufzeichnung bereitzustellen, aber das muss warten, bis er auf YouTube veröffentlicht und unter https://aka.ms/PSCommunityCall verlinkt wird.)

Basierend auf Ihren Ausführungen in der Aufnahme:

  • Da Sie sich bereit erklärt haben, dies erneut zu prüfen, öffnen Sie dieses Problem erneut und markieren Sie es erneut als Review - Committee .

  • Was Ihre Bemerkungen angeht, dass das Einschließen von Variablennamen in geschweifte Klammern eine bereits vorhandene Funktion ist und die Leute sich aus _ästhetischen_ Gründen dagegen wehren, sie in diesem Fall verwenden zu müssen:

    • Ich glaube nicht, dass sich hier irgendjemand _nicht_ bewusst ist, dass {...} _kann_ und manchmal _muss_ verwendet werden muss, um Variablennamen eindeutig zu machen.
    • Es geht auch nicht um _Ästhetik_, es geht in erster Linie darum, _nicht das erwartete Verhalten_ auf eine Art und Weise zu erhalten, die _leise fehlschlägt_, weil _in diesem Fall _nicht erwartet wird, {...} zu müssen_; ein zweites Problem sind die Unannehmlichkeiten beim Tippen.
GitHub
RFC-Dokumente (Request for Comments) für Community-Feedback zu Designänderungen und Verbesserungen am PowerShell-Ökosystem - PowerShell/PowerShell-RFC
Microsoft Teams

Ich mache mir Sorgen, dass dieses Thema - jetzt scheinbar auf unbestimmte Zeit in einem geschlossenen Zustand - durch die Ritzen fallen wird, daher habe ich #14025 als Erinnerung geöffnet, um es noch einmal zu besuchen, und ich lade alle Interessierten ein, dort ihre Unterstützung zu zeigen.

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen