Powershell: Sugestão: implemente condicionais ternários

Criado em 2 mar. 2017  ·  52Comentários  ·  Fonte: PowerShell/PowerShell

As condicionais ternárias de estilo C seriam uma adição útil à linguagem.

Por exemplo, em vez de escrever:

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

alguém poderia escrever:

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

Também aliviaria uma decepção de longa data:

Na Microsoft, “enviar é escolher”. Uma das coisas que ficamos muito desapontados por não poder enviar na V1.0 é um operador ternário.

De uma postagem no blog da equipe do PowerShell datada de 29 de dezembro de 2006.


Relacionado: implementar coalescência nula e imersão de nulos e atribuições condicionais nulas

Committee-Reviewed Issue-Enhancement WG-Language

Comentários muito úteis

@RichardSiddaway : Se olharmos no Stack Overflow para as perguntas marcadas do PowerShell _ feitas desde 2014_, obtemos (no momento desta redação):

$PSItem foi introduzido na v3 em setembro de 2012, então, por segurança, escolhi 2014 como a data de início da consulta.

Embora esta não seja uma métrica exata, - o site não permite que você pesquise $_ ou _ , infelizmente, e tenho certeza de que há perguntas que contêm _nenhum_ $_ nem $PSItem , e questões pré-v3 ainda estão sendo feitas - ainda acho que é seguro concluir que $_ é usado com muito mais frequência do que $PSItem .

No entanto, o ponto principal é que não há necessidade de _escolher_:

Assim como $PSItem e $_ coexistem alegremente, também ForEach-Object e % , Where-Object e ? , .. .:

$a ? $b : $c pode coexistir com if ($a) { $b } else { $c } / $(if ($a) { $b } else { $c })

Quanto a recapitular as razões _positivas_ para introduzir $a ? $b : $c

  • mais conciso, menos desordenado visualmente, usando uma sintaxe familiar à maioria dos programadores.

  • mais eficiente, porque não há necessidade de $(...) , que if instruções precisam para permitir seu uso como parte de uma expressão maior (que é mais ruidosa, menos eficiente e pode ter um lado não intencional efeitos)

Quanto à preocupação com a obscuridade:

Alguém que escreve _expressões_ (em oposição a meramente _invocar comandos_ com argumentos (simples)) pode ser considerado como tendo alguma experiência de desenvolvedor, e meu senso (anedótico) é que a maioria dos desenvolvedores pelo menos _reconhece_ $a ? $b : $c como um if condensado declaração

Mesmo que não o façam, no entanto, é facilmente explicado e, além do uso de _símbolos_ não óbvios, a complexidade conceitual é a mesma de if ($a) { $b } else { $c } , e ainda menor que
$(if ($a) { $b } else { $c })

Supondo que ele pega uma vez introduzido - certamente, esta discussão mostra que há demanda para ele - encontrá-lo com frequência o tornará um idioma familiar e facilmente reconhecível (que é mais conciso, mais fácil de digitar e, pelo menos para mim e alguns outros aqui, mais legível) - assim como a maioria das pessoas parece preferir $_ vez de $PSItem .

Todos 52 comentários

Observe que, com a mudança para permitir atribuições de instruções, a necessidade de um operador ternário é reduzida. Você pode simplesmente fazer
$var = if ($x) { $x } else { $y }
Não é tão conciso quanto o operador ternário, mas é indiscutivelmente mais legível.

Sim, embora você ainda tenha que usar $(...) _além_ se a condicional for parte de uma expressão maior:

'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')

Eu sei que a legibilidade está nos olhos do ... uh ... leitor, mas eu pessoalmente acho o último visualmente mais fácil de analisar, e ter que digitar menos é sempre um bônus.

Com um recurso usado com tanta frequência, acho que lembrar a sintaxe ternária mais abstrata não seria um problema (e, é claro, as pessoas podem continuar a usar if , se preferirem).

@ mklement0 Tenho que concordar que mais tarde tem menos carga cognitiva.

Isso está definitivamente na minha lista de favoritos.
@BrucePay , há algum motivo para isso ser uma má ideia? Ou trata-se apenas de 'enviar é escolher'?

No passado, essa solicitação de recurso foi rejeitada por ser mais difícil para os criadores de scripts menos experientes entenderem e que a forma de expressão da instrução if era uma alternativa mais clara, embora mais detalhada.

Minha perspectiva pessoal: se a linguagem fosse só para mim, provavelmente já a teria adicionado há muito tempo. Mas ... acho que muitos desenvolvedores não o usam, o que na verdade sugere que há alguma verdade na hipótese de que pessoas menos experientes terão problemas com o operador ternário.

@lzybkr :

Vale a pena distinguir entre o _ uso ativo_ de um recurso e a capacidade de _reconhecer_ e compreendê-lo.

Claramente, todos podem escolher se usarão tal recurso, mas você está dizendo que "ter problemas com" significa que pessoas menos experientes não irão _entendê-lo_ quando o virem no código de outras pessoas?

@ mklement0 - introduzimos $psitem como um apelido para $_ por causa do feedback suficiente de que $_ era enigmático e confuso, então eu acredito que o operador ternário seria difícil para menos pessoas experientes para entender.

Por outro lado, existem muitos elementos no PowerShell que são confusos para iniciantes ou até mesmo para desenvolvedores bastante experientes.

Como acontece com qualquer outra linguagem, é preciso algum esforço para aprender a sintaxe e o significado das construções da linguagem.
Não sei se acho o operador ternário especialmente difícil de entender.

Você tem dados sugerindo que sim?

Eu acredito que os únicos dados são anedóticos, mas a crítica se aplica a qualquer linguagem enigmática - bash, perl, etc.

E para ser claro, eu estava fornecendo o contexto histórico. Talvez o PowerShell seja onipresente o suficiente agora que uma sintaxe mais enigmática não afetará a adoção.

Também tenha em mente - algumas linguagens concisas ainda usam if / then como o operador ternário, por exemplo, F #.

Dito isso, talvez seja possível usar menos caracteres e não ser muito enigmático:

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

-then/-else se encaixa bem com a sintaxe do PowerShell - mas, um operador (ou operadores, se for muito confuso pensar em um único operador), você ganha o benefício de não precisar de parênteses e colchetes.

Então, novamente, isso está pedindo problemas semelhantes a foreach vs. foreach-object . mas talvez não seja tão ruim, não sei.

@lzybkr :

Críptico em doses homeopáticas é saudável:

O PowerShell não é elogiável em geral, mas em alguns casos oferece sintaxe criptografada como uma _alternativa_ concisa (você ainda pode ser prolixo, se desejar) para construções _frequentemente usadas_, notavelmente ? para Where-Object e % por ForEach-Object .

Fornecer $x ? $y : $z como uma alternativa concisa a if ($x) then { $y } else { $z } para mim segue o mesmo espírito.

O aspecto enigmático é melhorado por ? sendo uma reminiscência de uma _questão_ e, portanto, sugerindo uma condicional (embora _precedendo_ a ? neste caso) e - mais importante - sendo _uma construção potencialmente familiar de vários outras linguagens_, com a mesma semântica fundamental.

Você não obtém o mesmo benefício com $x -then $y -else $z : não é familiar.

Além disso, embora muitos operadores PS tenham nomes simbólicos, muitos não: * / + % ...
Eles também são inerentemente enigmáticos, simplesmente não os percebemos mais dessa forma, porque são tão familiares e onipresentes.

Minha impressão é que $x ? $y : $z também já é familiar para muitos, e se tornará ainda mais quando for introduzido na linguagem, dada a necessidade frequente de condicionais concisas.

Observe que você estará bastante limitado no que pode especificar com este operador. Em particular, você não poderá usar comandos a menos que os coloque entre parênteses:

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

comparado com

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

ou

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

vs

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

Na minha opinião, há pouca vantagem em termos de brevidade e uma desvantagem distinta na legibilidade. O operador ternário é muito menos interessante quando você tem uma linguagem orientada a expressões. Quando comecei a usar a linguagem, há 16 anos, adicionar o operador ternário parecia óbvio, vindo de uma formação C. Agora estou feliz por nunca o termos adicionado. Parece desordem.

Em particular, você não poderá usar comandos a menos que os coloque entre parênteses:

Isso se aplica ao operador _any_ PowerShell.

Nem todas as instruções do PowerShell envolvem comandos e, quando o fazem, os usuários já sabem que (...) é o preço de admissão para comandos (na maioria dos casos).

Em seu próprio exemplo, para mim ((test-path foo.txt) ? "foo.txt" : "bar.txt") bate $(if (test-path foo.txt) {"foo.txt"} else {"bar.txt"}) , tanto pela obscuridade de precisar de $(...) quanto pelo ruído introduzido pelas chaves.

Talvez seja só eu, mas eu acho isso:

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

maneira mais fácil de escanear / analisar visualmente do que esta:

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

Minha única reclamação sobre esse problema é que se você vai fazer ?: ternário, também deve fazer a coalescência nula ?? :

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

Eu vi uma série de implementações Invoke-Ternary e Invoke-NullCoalescing na natureza (por exemplo, https://github.com/dahlbyk/posh-git/blob/master/src/Utils.ps1#L12). Isso meio que indica que há um desejo geral por esse recurso embutido na linguagem.

@rkeithhill : Eu concordo; re coalescência nula: já existe um problema, que também cobre a saturação de nulos: # 3240

Portanto, o argumento de programadores menos experientes não seria capaz de usar facilmente uma instrução de código ternária ou de coalescência nula, eu acho que é um pouco míope. Não há requisitos para usar esses recursos "avançados" e se um programador não consegue ler o código porque não tem experiência, então pessoalmente essa é a minha dica de que preciso aprender algo novo muito rápido.
Quando vi um ternário em C # pela primeira vez, pensei que WTF é esse novo inferno que o MS introduziu, até que demorei alguns minutos para ler sobre isso, o que me deixou viciado.

Exemplo prático em POSH, tenho esta linha:
$mc_object = ($Message.fields | where Name -Match appname).Content
o que é bom e elegante, exceto quando o objeto $ Message não tem uma propriedade arquivada com um nome de "nome do aplicativo" e, como não controlo os dados formatados em JSON de onde eles vêm, tenho que determinar o que fazer.

Portanto, com operações de coalescência nula, tudo o que tenho que fazer é adicionar ?? "" no final para ter certeza de que $ mc_object sempre foi uma string válida, mesmo se o setter original fosse nulo. Caso contrário, eu teria que fazer algumas técnicas diferentes para realizar o que 4 pressionamentos de tecla podem fazer, como
$mc_object = if(-not ($Message.fields | where Name -Match appname).Content)){""}else{($Message.fields | where Name -Match appname).Content}
Isso para mim é muito ilegível, mas então posso limpar isso um pouco fazendo algo assim, que é o que estou fazendo.
$mc_object = ($Message.fields | where Name -Match appname).Content if(-not $mc_object){$mc_object = ""}

Embora não seja terrível, é um inferno de muito mais do que 4 teclas sendo pressionadas para coelasce nula.

De qualquer forma, eu definitivamente voto em ternário e nulo-coelasce no Powershell, ele adiciona alguns recursos muito avançados e apenas torna o Powershell mais atraente para usar na forma "central" em qualquer sistema.

@lzybkr Ainda não vi ninguém realmente adotar $PSItem . Trabalho em uma equipe decentemente grande de pessoas que escrevem scripts e ainda usam $_ , mesmo os usuários menos experientes do PowerShell.

@tibmeister ou ....

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

As atribuições como expressões passarão, mas são incrivelmente ilegíveis.

Eu uso regularmente $ psitem

Ao longo de vários anos julgando jogos de script, $ psitem foi muito usado nas respostas

@RichardSiddaway : Se olharmos no Stack Overflow para as perguntas marcadas do PowerShell _ feitas desde 2014_, obtemos (no momento desta redação):

$PSItem foi introduzido na v3 em setembro de 2012, então, por segurança, escolhi 2014 como a data de início da consulta.

Embora esta não seja uma métrica exata, - o site não permite que você pesquise $_ ou _ , infelizmente, e tenho certeza de que há perguntas que contêm _nenhum_ $_ nem $PSItem , e questões pré-v3 ainda estão sendo feitas - ainda acho que é seguro concluir que $_ é usado com muito mais frequência do que $PSItem .

No entanto, o ponto principal é que não há necessidade de _escolher_:

Assim como $PSItem e $_ coexistem alegremente, também ForEach-Object e % , Where-Object e ? , .. .:

$a ? $b : $c pode coexistir com if ($a) { $b } else { $c } / $(if ($a) { $b } else { $c })

Quanto a recapitular as razões _positivas_ para introduzir $a ? $b : $c

  • mais conciso, menos desordenado visualmente, usando uma sintaxe familiar à maioria dos programadores.

  • mais eficiente, porque não há necessidade de $(...) , que if instruções precisam para permitir seu uso como parte de uma expressão maior (que é mais ruidosa, menos eficiente e pode ter um lado não intencional efeitos)

Quanto à preocupação com a obscuridade:

Alguém que escreve _expressões_ (em oposição a meramente _invocar comandos_ com argumentos (simples)) pode ser considerado como tendo alguma experiência de desenvolvedor, e meu senso (anedótico) é que a maioria dos desenvolvedores pelo menos _reconhece_ $a ? $b : $c como um if condensado declaração

Mesmo que não o façam, no entanto, é facilmente explicado e, além do uso de _símbolos_ não óbvios, a complexidade conceitual é a mesma de if ($a) { $b } else { $c } , e ainda menor que
$(if ($a) { $b } else { $c })

Supondo que ele pega uma vez introduzido - certamente, esta discussão mostra que há demanda para ele - encontrá-lo com frequência o tornará um idioma familiar e facilmente reconhecível (que é mais conciso, mais fácil de digitar e, pelo menos para mim e alguns outros aqui, mais legível) - assim como a maioria das pessoas parece preferir $_ vez de $PSItem .

mklement0, você tem um exemplo incrível e acho que demonstra o ponto claramente, obrigado.

Relendo e revisitando isso e olhando para algumas das questões, encontro-me mais inclinado para as sintaxes um pouco mais prolixas sugeridas:

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

ou, para uma sintaxe mais legível semanticamente:

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

@ vexx32 Embora não me importe com seu primeiro exemplo, acho a condição no meio de uma expressão extremamente pesada.

Sim, eu acho que eu tendo a concordar, mas ele ler um pouco mais ... sem problemas. Mas eu ainda tenderia a ir para o primeiro.

Considerando que o PowerShell se destina a ser uma linguagem "em ascensão" para C #, acho que usar ? : é o caminho a percorrer. Até o JavaScript usa essa sintaxe e é uma das linguagens mais populares atualmente. :-)

Concordo, @rkeithhill , tanto pela familiaridade do constructo de várias outras linguagens _e_ pelo desejo de também ter atribuições de coalescência nula, saturação de ? também.

Os dois últimos - por exemplo, $foo?.bar e $var ?= 'default val' - não são realmente possíveis sem uma representação baseada em símbolos, e mesmo para coalescência nula $a ?? 'value-if-null' parece preferível a algo como $a -elseifnull 'value-if-null' .

Lembre-se de que ? , como um apelido freqüentemente usado para Where-Object , já está firmemente enraizado como representando uma _condicional_, portanto, transferir esse conhecimento para variações de seu uso parece lógico.

O PowerShell é realmente uma rampa de acesso ao C #? Eu sei que era uma intenção declarada há 10-12 anos, mas isso está realmente acontecendo? Minha suspeita é que, para a maioria dos usuários do PowerShell, C # não é o lugar que eles querem ir.

se as condicionais ternárias acontecerem, prefiro ver algo como
$ value = $ trueVal -if $ a -eq $ b -else $ falseVal

como mencionado por @ vexx32

Faz mais sentido para o usuário médio do PowerShell.

@ mklement0 Meus comentários sobre $ psitem foram baseados em minha experiência pessoal. Se você teve uma experiência diferente, isso não invalida minha experiência

eu sei que era uma intenção declarada há 10-12 anos

Sim, nas primeiras cúpulas do MVP, entre outros lugares, por Jeffrey. Não ouvi nada diferente desde então.

Além disso, quase todas as construções condicionais / loop partem de C # (e da linhagem C), if {} , while {} , do {} while , switch {} , para {} , foreach {} , try {} catch {} finally {} `. Para mim, faz sentido que essa construção condicional também o faça.

No entanto, essas são palavras-chave de linguagem, @rkeithhill. Os operadores são totalmente diferentes.

Acho que você descobrirá que a grande maioria dos operadores usados ​​no PowerShell são bastante diferentes de seus equivalentes em C #. A equipe PS optou muito claramente por uma sintaxe mais descritiva para a maioria dos operadores.

Eu consideraria que o comportamento ternário também deveria seguir as opções de sintaxe mais detalhadas disponíveis. O PowerShell pode ter sido concebido como um 'avanço' para o C #, mas isso não significa que ele deva herdar suas sintaxes mais simbólicas. Na verdade, existem muitos lugares onde isso foi cuidadosamente evitado .

Considere, se quiser, que seus argumentos para a sintaxe simbólica estão enraizados em como outras linguagens de programação comuns representam esse conceito. O PowerShell não foi por esse caminho na postagem, em vez disso, preferiu trabalhar com uma sintaxe tão descritiva quanto possível. Simplesmente porque aqueles que já têm experiência em C # estão familiarizados com essa sintaxe certamente não é uma razão para usá-la.

Se o PowerShell é uma linguagem 'em ascensão' para C # ou qualquer outra linguagem (que, eu acho, funciona muito bem até agora), então precisamos considerar o menor denominador comum aqui e pensar sobre o que as pessoas mais inexperientes encontrariam sensato e intuitivo .

Não estou dizendo que as minhas soluções oferecidas são, mas eu acho que eles estão possivelmente dirigido em uma direção mais sensata a partir dessa perspectiva.

@ vexx32
E quanto a essas operadoras?

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

Geralmente, concordo que seguir o exemplo do C # nem sempre é apropriado e que a preservação do espírito do PowerShell deve ter prioridade.

Por outro lado, eu desaconselho o desvio do C # nos casos em que a mesma sintaxe parece ser um ajuste plausível, e para mim a proposta em mãos - junto com # 3240 - é um exemplo disso.

Se deixarmos as outras línguas de lado:

  • A semântica atual de ? plausivelmente se estende aos operadores propostos.

  • Se você vir valor nos operadores _related_ sendo propostos - saturação de nulos ( ?. ), coalescência de nulos ( ?? ) e atribuição condicional nula ( ?= ) - então optando para uma forma ternária detalhada como -then / -else não é uma opção, se você quiser que todos esses operadores relacionados reflitam uma semelhança (o que eles obviamente têm conceitualmente).

Quanto mais exótico for um recurso, mais verbosidade é importante.

Quanto mais freqüentemente usado um recurso, mais concisão é importante. E a abstração de uma representação baseada em símbolos deixa de ser um problema por meio da simples exposição repetida à sintaxe - assim como com * , por exemplo.

Todos os operadores que estão sendo discutidos comigo se enquadram na última categoria.


@RichardSiddaway :

Meus comentários sobre $ psitem foram baseados em minha experiência pessoal. Se você teve uma experiência diferente, isso não invalida minha experiência

Sim, seus comentários foram baseados na experiência _pessoal_.
Os meus foram baseados na _análise de dados_ do popular site de perguntas e respostas Stack Overflow, para inferir padrões de uso _geral_ (dentro das restrições declaradas) - o que não está relacionado à minha experiência pessoal.

A única razão pela qual você poderia perceber meus comentários como invalidando os seus se você acredita que suas observações pessoais refletem uma verdade "transpessoal" - uma afirmação que você não fez como tal em seus comentários. Você quis fazer isso? Nesse caso, precisamos discutir _isso_.

Quase todos esses operadores são operadores matemáticos com significado relativamente claramente compreendido, @ mklement0 😄

Um operador ternário é um operador condicional e _todos_ os operadores booleanos / condicionais de PS são da forma mais detalhada: -and , -or , -eq , -ne , -contains , etc.

Eu concordo que esta abreviação pode fazer sentido devido à necessidade de recursos circundantes e operadores relacionados, entretanto. Mas eu realmente acho que a sintaxe ternária "padrão" não é particularmente intuitiva para aqueles de nós que ainda não foram expostos repetidamente a ela.

operadores são operadores matemáticos

Entre os listados, apenas + - * / % tem significado (puramente) matemático, mas o aspecto claramente compreendido se aplica aos outros também (com exceção de = , dado que é frequentemente confundido com teste de igualdade )

A melhor construção para comparar <condition> ? <if-true> : <else> é a if _statement_, não outros operadores. Embora if seja definitivamente mais prolixo, é precisamente esse aspecto que a operação ternária deve abordar (além de ser uma expressão verdadeira e combinável, ao contrário de if ).

Existe um espectro de concisão, com certeza, mas, como você disse, para acomodar todos os operadores relacionados sendo propostos de uma forma consistente, uma sintaxe baseada em símbolos faz sentido.

para aqueles de nós que ainda não foram repetidamente expostos a ele.

Bem, espero que isso mude em breve. 😁
Entendi, mas (a) a sintaxe é facilmente explicada e tem a mesma complexidade conceitual de uma instrução if e (b) a exposição repetida deve ajudar na retenção de memória.

@ mklement0 Como você sugere que ? seja um caractere de nome válido? Quebrando a mudança? Eu considero as pessoas no núcleo do PowerShell bem versadas no PowerShell como ele é e que a sintaxe adicional (que existe em outras línguas por quase 50 anos) não será um obstáculo. Eles sempre podem usar if/else se quiserem mais verbosidade.

? é apenas um apelido válido no modo de comando ; em todas as variantes do modo de expressão , é simplesmente um caractere inválido no momento. Não há colisão.

Se você tentar inserir este código, ele simplesmente apresentará um erro:

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

Resultado:

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

Em seu exemplo de absorção de nulos: $var?.maybenull() não se importa se houver um ponto de interrogação ali e se alguém estiver tentando condensar demais, seu ternário quebrará.

Desculpe, isso estava sendo discutido principalmente na outra edição, então não achei que você estivesse se referindo a isso.

Se podemos ou não impedir que seja um caractere de nome de variável válido é com a equipe PS, mas estou inclinado a ser da opinião que evitar que ele seja considerado um caractere de nome de variável por padrão não seria muito importante. Acho que nunca vi alguém realmente usar ? como parte do nome de uma variável.

@ vexx32 Sim, devo trazer isso aí. Isso pode ter impactos adicionais se não for cuidadoso com o escopo (embora isso já seja visto em expansões de coluna, então as pessoas devem estar familiarizadas com isso):

$var = $test?$thing1:$thing2

mas posso estar raciocinando demais em casos extremos para aqueles de nós que vivem na concha.

Corrigido:

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

@ mklement0 - Não concordo necessariamente com:

A melhor construção para comparar?:to é a instrução if, não outros operadores. Embora if seja definitivamente mais prolixo, é precisamente esse aspecto que a operação ternária deve abordar (além de ser uma expressão verdadeira e combinável, ao contrário de if).

Especificamente, o operador ternário existe porque C / C # são linguagens orientadas a instruções, mas precisam de expressões condicionais.

Em linguagens orientadas a expressões (por exemplo, F # ou Rust), não há sintaxe concisa, pois é considerada desnecessária. Eu acho que essa velha discussão sobre Rust removendo o operador ternário é interessante.

Uma coisa que eu realmente gosto no Rust é o uso do operador ? para tratamento de erros. Não tenho uma proposta concreta para usar ? no PowerShell, mas parece que ? poderia ser melhor usado para tratamento de erros do que para uma expressão condicional.

@ TheIncorrigible1 , @ vexx32 : Sim, a imersão de nulos seria tecnicamente uma alteração importante, mas com sorte do tipo bucket 3 (na verdade, vamos continuar a discussão lá); para a operação ternária, o uso sugerido de {...} / espaço em branco antes de ? para desambiguação parece resolver esse problema.

@lzybkr :

Especificamente, o operador ternário existe porque C / C # são linguagens orientadas a instruções, mas precisam de expressões condicionais.

Bem, no PowerShell, as instruções de controle de fluxo, como if são expressões _half_; em expressões _simple_, a operação ternária proposta seria equivalente; em _nested_, não iria:

$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

A necessidade de $() / @() é mais do que apenas um inconveniente de sintaxe: tem implicações comportamentais e de desempenho.

Dito isso, eu _desejo_ que declarações como if e foreach sejam expressões genuínas (mais dois exemplos de coisas que estão falhando: foreach ($i in 1..5) { $i } | Write-Output ou foreach ($i in 1..5) { $i } > out.txt ).
Eu não sei o suficiente para julgar se eles _não podem ser_, no entanto e / ou se há uma preocupação de compatibilidade com versões anteriores.
Veja também: # 6817


Se if se tornasse uma expressão completa no PowerShell, você poderia apresentar o argumento que levou à remoção da condicional ternária de Rust: então não é mais _necessário_.

No entanto, minha motivação para esta proposta nunca foi a _necessidade_ - trata-se de concisão, conveniência e legibilidade (desordem visual).


Não tenho uma proposta concreta para usar? no PowerShell, mas parece? poderia ser melhor usado para tratamento de erros do que para uma expressão condicional.

Acho que introduzir ? com semânticas fundamentalmente diferentes do C # seria uma fonte de confusão eterna.

Separadamente, as melhorias no tratamento de erros do PowerShell valem a pena discutir.

Se estamos procurando uma alternativa concisa, mas não intuitiva, para If / Then / Else, já temos uma.

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

E funciona em expressões.

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

@TimCurwick : Isso é conciso (e mais obscuro), mas não equivalente: a condicional ternária proposta seria _short-circuiting_ (assim como uma instrução if ), enquanto sua sintaxe invariavelmente avalia _both_ alternativas.

Dito isso, sua sintaxe é certamente a próxima melhor opção disponível atualmente, supondo que alguém esteja ciente da limitação declarada.

Com relação à discussão sobre como exibir opções ternárias no PowerShell, alguém considerou uma opção no mesmo formato usado por -replace / .replace() ?

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

ou

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

Isso deixaria claro que o operador está executando uma ação ternária, chamando-a literalmente de ternária . É prolixo, mas ainda curto para escrever e faz uso do comportamento comum existente de -operator $first,$second , por isso deve parecer familiar para usuários do PowerShell em todas as faixas de experiência

🤔 pode funcionar, mas seria mais estranho do que qualquer uma das alternativas propostas. -replace funciona dessa forma porque apenas aceita uma matriz real de argumentos. .Replace() não é gerenciado pela equipe PS - é um método na classe .NET System.String .

Se tentarmos usar qualquer uma dessas sintaxes, isso significará um método ETS (que é OK, mas tende a adicionar um pouco de sobrecarga de desempenho para a criação de objetos aos quais ele precisa ser anexado) ou, com a versão do operador você propõe, não poderíamos facilmente ter um array como argumento.

Sem um operador especial como esse no analisador, não poderíamos entrar em curto-circuito. As sintaxes ternárias em outras línguas geralmente existem porque você _não quer_ avaliar realmente as duas opções; o tempo de computação é mais rápido se apenas o branch correto precisa ser avaliado, em vez de avaliar completamente as duas opções (o que pode vir com alguns efeitos colaterais significativos).

E uma vez que isso já exigiria maiúsculas e minúsculas, seria mais eficaz introduzir uma nova sintaxe para ele, para minimizar a confusão (seria um pouco enganador ter algo que se parece com uma matriz, mas não pode ser usado como uma; não suportaria criar o "array" antes do tempo e passar isso como uma variável, por exemplo). O fato de que os argumentos do método já entram em conflito um pouco com a sintaxe do array costuma ser enganoso. Não acho que gostaria de adicionar um _terceiro_ comportamento variante para vírgulas à mistura.

@ PowerShell / powershell-Committee discutiu isso longamente, nem todos concordamos, mas a maioria concorda que há valor em ter esse operador e se alinhar com a sintaxe C # mantendo ?: pois a expectativa é de que a maior parte do uso será ser de desenvolvedores C #. Este recurso será Experimental, com feedback de uso real pendente.

@ SteveL-MSFT Então isso significa que o recurso está avançando para o 7.0? Irá quebrar a compatibilidade em variáveis ​​que podem usar ? em seus símbolos?

@ TheIncorrigible1 sim, esse recurso está avançando no PS7. Não deve quebrar a compatibilidade com o uso de ? alias. Há uma preocupação com a acuidade visual de ? ao olhar para um script tentando diferenciar Where-Object e ternary , mas veremos qual é o feedback do usuário sobre isso. Em geral, não esperamos que a maioria dos usuários use essa operadora, mas isso não deve impedi-la de seguir em frente.

@ SteveL-MSFT, quero dizer variáveis ​​com um nome de $isValid? ou semelhante. Esses são tokens válidos na iteração atual do PS.

@ TheIncorrigible1 :

Exigir espaço em branco entre o primeiro operando e ? resolve esse problema, como sugerido anteriormente, e para mim é uma solução perfeitamente razoável:

  • O : _also_ requer espaço em branco ao redor dele, porque algo como $true ? $number:42 não funcionaria, dado que $number:42 seria _como um todo_ seria interpretado como uma única referência de variável.

  • Embora C # _does_ permita true?number:42 , não acho que precisamos - ou, na verdade, podemos - nos preocupar com a compatibilidade nesse nível. Eu pessoalmente valorizo ​​a concisão, mas não em detrimento da legibilidade; mesmo se eu _pudesse_ escrever $true?$number:42 , não o faria.

(A compatibilidade com versões anteriores será de fato um problema quando (dica, dica) implementarmos o acesso condicional nulo . A permissividade do PowerShell com relação aos nomes de identificadores é geralmente problemática, como @KirkMunro argumentou recentemente, mas o navio partiu )

Sim, acho que deixar o requisito de espaço em branco é sensato. Afinal, é conciso o suficiente. 😁

O protótipo tentou muito analisar os números com ? e : neles de maneira diferente no contexto do operador ternário (onde sabemos que estamos esperando uma expressão). Então você pode escrever coisas como ${isWindows}?12:47 .
Números como 123? ou 1:23 são tokenizados como um token genérico hoje, o que não é útil no caso em que sabemos que estamos esperando uma expressão.

Para variáveis, nenhuma mudança em como ? ou : podem ser usados ​​para o nome da variável, uma vez que a variável é uma expressão.

Bom ponto, @ daxian-dbw; Esqueci que {...} pode ser usado para resolver qualquer ambigüidade de limite de nome de variável, então acho que jogadores de golfe de código poderiam usar algo como ${isWindows}?${number}:47

Podemos fechar isso agora?

Fechar via # 10367

Esta página foi útil?
0 / 5 - 0 avaliações