Powershell: Предложение: реализовать тернарные условные выражения

Созданный на 2 мар. 2017  ·  52Комментарии  ·  Источник: PowerShell/PowerShell

Тернарные условные выражения в стиле C были бы удобным дополнением к языку.

Например, вместо того, чтобы писать:

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

можно было написать:

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

Это также избавило бы от давнего разочарования:

В Microsoft «отгрузить - значит выбрать». Одна из вещей, которые мы были очень разочарованы невозможностью реализовать в V1.0, - это тернарный оператор.

Из сообщения в блоге команды PowerShell от 29 декабря 2006 г.


Связано: реализовать присваивания с объединением нулей, пропиткой нулем и условным нулевым значением.

Committee-Reviewed Issue-Enhancement WG-Language

Самый полезный комментарий

@RichardSiddaway : Если мы посмотрим на Stack Overflow на вопросы с тегами PowerShell, которые задаются с 2014 года, мы получим (на момент написания этой статьи):

$PSItem был представлен в версии 3 в сентябре 2012 года, поэтому на всякий случай я выбрал 2014 год в качестве даты начала запроса.

Хотя это не точная метрика, - сайт не позволяет вам искать $_ или _ , к сожалению, и я уверен, что есть вопросы, содержащие _neither_ $_ nor $PSItem , и вопросы до версии 3 все еще задаются - я все еще думаю, что можно с уверенностью заключить, что $_ используется гораздо чаще, чем $PSItem .

Однако важнее то, что нет необходимости _выбирать_:

Как $PSItem и $_ счастливо сосуществуют, так и ForEach-Object и % , Where-Object и ? , .. .:

$a ? $b : $c может сосуществовать с if ($a) { $b } else { $c } / $(if ($a) { $b } else { $c })

Что касается повторения _позитивных_ причин для введения $a ? $b : $c

  • более сжатый, менее загроможденный визуально, с использованием синтаксиса, знакомого большинству программистов.

  • более эффективен, потому что нет необходимости в $(...) , которые необходимы операторам if , чтобы их можно было использовать как часть более крупного выражения (которое более шумно, менее эффективно и может иметь непреднамеренную сторону последствия)

Что касается озабоченности по поводу неизвестности:

Кто-то пишет _expressions_ (в отличие от простого _invoking команд_ с (простыми) аргументами), как можно предположить, имеет некоторый опыт разработчика, и я (неофициально) полагаю, что большинство разработчиков по крайней мере _recognize_ $a ? $b : $c как сжатое if , независимо от того, активно ли они его используют.

Однако даже если они этого не делают, это легко объяснить, и, за исключением использования неочевидных _символов_, концептуальная сложность такая же, как у if ($a) { $b } else { $c } , и даже меньше, чем
$(if ($a) { $b } else { $c })

Если предположить, что он завоевывает популярность после того, как его представили - конечно, это обсуждение показывает, что на него есть спрос - частое столкновение с ним сделает его знакомым и легко узнаваемым идиомом (который более краток, легче набирается и, по крайней мере, для меня и некоторых других здесь, более читабельно) - как и большинство людей, кажется, предпочитают $_ $PSItem .

Все 52 Комментарий

Обратите внимание, что с изменением, разрешающим присваивания из операторов, потребность в тернарном операторе уменьшается. Вы можете просто сделать
$var = if ($x) { $x } else { $y }
Он не такой лаконичный, как тернарный оператор, но, возможно, более читабелен.

Да, хотя вам все равно придется использовать $(...) _in addition_, если условное выражение является частью более крупного выражения:

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

против.

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

Я знаю, что удобочитаемость в глазах ... эээ ... читателя, но я лично считаю, что последний визуально легче анализировать, а необходимость печатать меньше - всегда бонус.

Я думаю, что с такой часто используемой функцией запоминание более абстрактного тернарного синтаксиса не будет проблемой (и, конечно, люди могут продолжать использовать if , если захотят).

@ mklement0 Должен согласиться позже, когнитивная нагрузка у него меньше.

Это определенно в моем списке.
@BrucePay , есть ли причины, по которым это было бы плохой идеей? Или это просто «отгрузить - значит выбрать»?

В прошлом этот запрос функции отвергался, так как менее опытным разработчикам сценариев было труднее понять, и что форма выражения оператора if была более ясной, но более подробной альтернативой.

Моя личная точка зрения: если бы язык был только для меня, я бы, наверное, уже давно добавил его. Но ... Я считаю, что многие разработчики не используют его, что на самом деле предполагает некоторую правду в гипотезе о том, что у менее опытных людей будут проблемы с тернарным оператором.

@lzybkr :

Стоит различать _активное использование_ функции и способность _ распознать_ и понять ее.

Ясно, что каждый может выбрать, использовать ли такую ​​функцию, но вы говорите, что «иметь проблемы с» означает, что менее опытные люди не будут _ понимать_ это, когда они видят это в коде других?

@ mklement0 - мы ввели $psitem в качестве псевдонима для $_ из-за достаточной обратной связи, что $_ было загадочным и запутанным, поэтому я действительно считаю, что тернарный оператор будет трудным для некоторых менее опытные люди разбираются.

С другой стороны, в PowerShell есть много элементов, которые сбивают с толку новичков или даже довольно опытных разработчиков.

Как и в случае с любым другим языком, для изучения синтаксиса и значения языковых конструкций требуются определенные усилия.
Я не знаю, думаю ли я, что тернарный оператор особенно труден для понимания.

Есть ли у вас данные, подтверждающие это?

Я считаю, что все данные анекдотичны, но критика относится к любому загадочному языку - bash, perl и т. Д.

И чтобы быть ясным, я привел исторический контекст. Возможно, PowerShell теперь достаточно повсеместен, и более загадочный синтаксис не повлияет на принятие.

Также имейте в виду - некоторые краткие языки все еще используют if / then в качестве тернарного оператора, например F #.

Тем не менее, возможно, можно использовать меньше символов и не быть слишком загадочным:

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

-then/-else хорошо сочетается с синтаксисом PowerShell, но, используя оператор (или операторы, если их сложно рассматривать как один оператор), вы получаете преимущество, так как вам не нужны парные скобки и фигурные скобки.

Опять же, это вызывает проблемы, похожие на foreach vs. foreach-object . но может все не так плохо, не знаю.

@lzybkr :

Cryptic в гомеопатических дозах - это здорово:

PowerShell, в целом, похвально не является загадочным, но в некоторых случаях предлагает загадочный синтаксис в виде краткого _альтернативного_ (при желании вы все равно можете быть подробным) для _ часто используемых_ конструкций, особенно ? для Where-Object и % за ForEach-Object .

Предоставление мне $x ? $y : $z в качестве краткой альтернативы if ($x) then { $y } else { $z } - в том же духе.

Загадочный аспект улучшается за счет того, что ? напоминает _question_ и, следовательно, предлагает условное (хотя и _предшествующее_ ? в данном случае) и, что более важно, _ потенциально знакомая конструкция из нескольких другие языки_ с той же фундаментальной семантикой.

Вы не получите того же преимущества с $x -then $y -else $z : это не знакомо.

Кроме того, хотя многие операторы PS имеют символические имена, многие из них не имеют: * / + % ...
Они тоже по своей сути загадочны, просто мы больше не воспринимаем их так, потому что они настолько знакомы и повсеместны.

Мне кажется, что $x ? $y : $z тоже уже знакомо многим и станет еще более знакомым после введения в язык, учитывая частую потребность в кратких условных выражениях.

Обратите внимание, что вы будете довольно ограничены в том, что вы можете указать с помощью этого оператора. В частности, вы не сможете использовать команды, если не заключите их в круглые скобки:

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

по сравнению с

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

или

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

против

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

На мой взгляд, это небольшое преимущество с точки зрения краткости и явный недостаток в удобочитаемости. Тернарный оператор гораздо менее интересен, когда у вас есть язык, ориентированный на выражения. Когда я начал работать с языком 16 лет назад, добавление тернарного оператора казалось очевидным, исходя из фона C. Теперь я рад, что мы его не добавили. Это просто похоже на беспорядок.

В частности, вы не сможете использовать команды, если не заключите их в круглые скобки:

Это относится к _любому_ оператору PowerShell.

Не все операторы PowerShell включают команды, и когда они это делают, пользователи уже знают, что (...) - это цена допуска для команд (в большинстве случаев).

В вашем собственном примере для меня ((test-path foo.txt) ? "foo.txt" : "bar.txt") превосходит $(if (test-path foo.txt) {"foo.txt"} else {"bar.txt"}) , как из-за неясности необходимости $(...) и из-за шума, создаваемого фигурными скобками.

Может быть, это только я, но я нахожу вот это:

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

способ проще визуально сканировать / анализировать, чем это:

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

Моя единственная жалоба на эту проблему заключается в том, что если вы собираетесь использовать тройной ?: вам также следует выполнить объединение с нулевым значением ?? :

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

Я видел несколько реализаций Invoke-Ternary и Invoke-NullCoalescing в дикой природе (например, https://github.com/dahlbyk/posh-git/blob/master/src/Utils.ps1#L12). Такой тип означает, что есть общее желание, чтобы такая функция была встроена в язык.

@rkeithhill : Согласен; re null-coalescing: уже существует проблема, которая также касается нулевого замачивания: # 3240

Таким образом, аргумент менее опытных программистов не сможет легко использовать объединяющий нуль или оператор тернарного кода, я думаю, это немного недальновидно. Нет необходимости использовать эти «продвинутые» функции, и если программист не может прочитать код из-за недостатка опыта, то лично мне кажется, что мне нужно очень быстро изучить что-то новое.
Когда я впервые увидел троичный язык на C #, я подумал, что WTF - это новый ад, который представила MS, пока мне не потребовалось несколько минут, чтобы прочитать об этом, что потом меня зацепило.

Практический пример в POSH, у меня есть такая строчка:
$mc_object = ($Message.fields | where Name -Match appname).Content
что хорошо и красиво, за исключением случаев, когда объект $ Message не имеет свойства filed с именем "app name", и поскольку я не контролирую данные в формате JSON, из которых оно исходит, я должен определить, что делать.

Итак, с операциями объединения с нулевым значением все, что мне нужно сделать, это добавить ?? "" в конце, чтобы убедиться, что $ mc_object всегда был допустимой строкой, даже если исходный установщик был нулевым. В противном случае мне пришлось бы использовать несколько разных методов, чтобы выполнить то, что могут сделать 4 нажатия клавиши, например
$mc_object = if(-not ($Message.fields | where Name -Match appname).Content)){""}else{($Message.fields | where Name -Match appname).Content}
Для меня это очень нечитабельно, но потом я могу немного очистить это, сделав что-то вроде этого, что я и делаю.
$mc_object = ($Message.fields | where Name -Match appname).Content if(-not $mc_object){$mc_object = ""}

Хотя это и не страшно, это чертовски много больше, чем 4 клавиши, нажатые для нулевого коэласа.

Как бы то ни было, я определенно голосую за тернарность и нулевое коэлассирование в Powershell, это добавляет некоторые очень продвинутые функции и просто делает Powershell более привлекательным для использования в «базовой» форме в любой системе.

@lzybkr Я еще не видел, чтобы кто-нибудь действительно принимал $PSItem . Я работаю в довольно большой команде людей, которые пишут сценарии, и все они по-прежнему используют $_ , даже менее опытные пользователи PowerShell.

@tibmeister или ....

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

Присваивания в виде выражений проходят, но они невероятно нечитаемы.

Я регулярно использую $ psitem

За несколько лет судейства скриптовых игр $ psitem часто использовался в ответах.

@RichardSiddaway : Если мы посмотрим на Stack Overflow на вопросы с тегами PowerShell, которые задаются с 2014 года, мы получим (на момент написания этой статьи):

$PSItem был представлен в версии 3 в сентябре 2012 года, поэтому на всякий случай я выбрал 2014 год в качестве даты начала запроса.

Хотя это не точная метрика, - сайт не позволяет вам искать $_ или _ , к сожалению, и я уверен, что есть вопросы, содержащие _neither_ $_ nor $PSItem , и вопросы до версии 3 все еще задаются - я все еще думаю, что можно с уверенностью заключить, что $_ используется гораздо чаще, чем $PSItem .

Однако важнее то, что нет необходимости _выбирать_:

Как $PSItem и $_ счастливо сосуществуют, так и ForEach-Object и % , Where-Object и ? , .. .:

$a ? $b : $c может сосуществовать с if ($a) { $b } else { $c } / $(if ($a) { $b } else { $c })

Что касается повторения _позитивных_ причин для введения $a ? $b : $c

  • более сжатый, менее загроможденный визуально, с использованием синтаксиса, знакомого большинству программистов.

  • более эффективен, потому что нет необходимости в $(...) , которые необходимы операторам if , чтобы их можно было использовать как часть более крупного выражения (которое более шумно, менее эффективно и может иметь непреднамеренную сторону последствия)

Что касается озабоченности по поводу неизвестности:

Кто-то пишет _expressions_ (в отличие от простого _invoking команд_ с (простыми) аргументами), как можно предположить, имеет некоторый опыт разработчика, и я (неофициально) полагаю, что большинство разработчиков по крайней мере _recognize_ $a ? $b : $c как сжатое if , независимо от того, активно ли они его используют.

Однако даже если они этого не делают, это легко объяснить, и, за исключением использования неочевидных _символов_, концептуальная сложность такая же, как у if ($a) { $b } else { $c } , и даже меньше, чем
$(if ($a) { $b } else { $c })

Если предположить, что он завоевывает популярность после того, как его представили - конечно, это обсуждение показывает, что на него есть спрос - частое столкновение с ним сделает его знакомым и легко узнаваемым идиомом (который более краток, легче набирается и, по крайней мере, для меня и некоторых других здесь, более читабельно) - как и большинство людей, кажется, предпочитают $_ $PSItem .

mklement0, у вас есть отличный пример, который, я думаю, ясно демонстрирует суть дела, спасибо.

Перечитывая и пересматривая это и просматривая некоторые вопросы, я обнаружил, что склоняюсь к чуть более подробным синтаксисам, предлагаемым:

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

или, для более семантически читаемого синтаксиса:

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

@ vexx32 Хотя я не возражаю против вашего первого примера, я считаю условие в середине выражения чрезвычайно тяжелым.

Да, я думаю , что я склонен согласиться, но это немного далее ... гладко. Но я бы все равно выбрал первый.

Учитывая, что PowerShell задумывался как «быстрорастущий» язык для C #, я думаю, что использование ? : - лучший вариант. Даже JavaScript использует этот синтаксис, и в наши дни это один из самых популярных языков. :-)

Согласен, @rkeithhill , как за знакомство конструкции с несколькими другими языками _, так и за желание иметь также присваивания с объединением нуля, замачиванием нуля и условным присваиванием нулю , которые в C # также основаны на ? .

Последние два - например, $foo?.bar и $var ?= 'default val' - на самом деле невозможны без символьного представления, и даже для объединения с нулем $a ?? 'value-if-null' кажется предпочтительнее чем-то вроде $a -elseifnull 'value-if-null' .

Помните, что ? , как часто используемый псевдоним для Where-Object , уже прочно закрепился как представление _conditional_, поэтому перенос этих знаний в варианты его использования кажется логичным.

Действительно ли PowerShell является переходом на C #? Я знаю, что это было заявлено 10-12 лет назад, но так ли это на самом деле? Я подозреваю, что для большинства пользователей PowerShell C # - это не то, чего они хотят.

если будут возникать тернарные условные выражения, я бы предпочел увидеть что-то вроде
$ value = $ trueVal -if $ a -eq $ b -else $ falseVal

как упомянуто @ vexx32

Это имеет больше смысла для среднего пользователя PowerShell.

@ mklement0 Мои комментарии о $ psitem были основаны на моем личном опыте. Если у вас был другой опыт, это не отменяет моего опыта

я знаю, что это было заявленное намерение 10-12 лет назад

Ага, на ранних саммитах MVP Джеффри. С тех пор я ничего не слышал.

Кроме того, почти все условные конструкции / конструкции цикла берутся из C # (и происхождения C), if {} , while {} , do {} while , switch {} , для {} , foreach {} , try {} catch {} finally {} `. Мне кажется логичным, что эта условная конструкция тоже.

Но это ключевые слова языка, @rkeithhill. Операторы совершенно разные.

Я думаю, вы обнаружите, что подавляющее большинство операторов, используемых в PowerShell, сильно отличаются от их эквивалентов в C #. Команда PS явно выбрала более описательный синтаксис для большинства операторов.

Я считаю, что троичное поведение также должно соответствовать более подробным доступным параметрам синтаксиса. PowerShell, возможно, был задуман как переход к C #, но это не значит, что он должен унаследовать свой более символический синтаксис. Действительно, есть много мест, где этого старательно избегали .

Считайте, если хотите, что ваши аргументы в пользу символического синтаксиса уходят корнями в то, как другие распространенные языки программирования представляют эту концепцию. PowerShell не был тем, кто пошел по этому пути в публикации, вместо этого предпочитая работать с настолько информативным синтаксисом, насколько это можно сделать разумным. Просто потому, что те, кто уже имеет опыт работы с C #, знакомы с таким синтаксисом, безусловно, не является причиной для его использования.

Если PowerShell - это язык, переходящий в C # или любой другой язык (который, как мне кажется, пока неплохо работает), то нам нужно рассмотреть здесь наименьший общий знаменатель и подумать о том, что найдут самые неопытные люди. разумно и интуитивно понятно .

Я не говорю , что мои выдвигаемые решения, но я думаю , что они , возможно , движется в более разумном направлении с этой точки зрения.

@ vexx32
Как насчет этих операторов?

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

В целом я согласен с тем, что следовать примеру C # не всегда уместно и что сохранение духа PowerShell должно иметь приоритет.

И наоборот, я бы посоветовал не отклоняться от C # в тех случаях, когда тот же синтаксис действительно кажется правдоподобным, и для меня предлагаемое предложение - вместе с # 3240 - является примером этого.

Если оставить в стороне другие языки:

  • Текущая семантика ? правдоподобно распространяется на предложенные операторы.

  • Если вы видите значение в предлагаемых _related_ операторах - замачивании нуля ( ?. ), объединении нуля ( ?? ) и условном присваивании null ( ?= ) - тогда выбор для многословной тернарной формы, такой как -then / -else не подходит, если вы хотите, чтобы все эти связанные операторы отражали общность (которая, очевидно, концептуально есть).

Чем экзотичнее функция, тем важнее ее многословие.

Чем чаще используется функция, тем важнее ее сжатие. А абстрактность символьного представления перестает быть проблемой из-за многократного повторения синтаксиса - как, например, с * .

Все обсуждаемые мной операторы попадают в последнюю категорию.


@RichardSiddaway :

Мои комментарии о $ psitem были основаны на моем личном опыте. Если у вас был другой опыт, это не отменяет моего опыта

Да, ваши комментарии основаны на _личном_ опыте.
Мои были основаны на _анализе данных_ из популярного сайта вопросов и ответов Stack Overflow, чтобы сделать вывод о _ общих_ шаблонах использования (в пределах заявленных ограничений), что не связано с моим личным опытом.

Единственная причина, по которой вы могли воспринимать мои комментарии как аннулирующие ваши, если верите, что ваши личные наблюдения отражают «трансперсональную» правду - утверждение, которое вы не делали как таковое в своих комментариях. Вы хотели это сделать? Если так, нам нужно обсудить _это_.

Почти все эти операторы являются математическими операторами с относительно понятным значением, @ mklement0 😄

Тернарный оператор - это условный оператор, и _все_ логических / условных операторов PS имеют более подробную форму: -and , -or , -eq , -ne , -contains и т. Д.

Я согласен с тем, что это сокращение может иметь смысл из-за необходимости использования окружающих функций и связанных операторов. Но я действительно думаю, что «стандартный» тернарный синтаксис не особенно интуитивно понятен для тех из нас, кто еще не сталкивался с ним неоднократно.

операторы математические операторы

Среди перечисленных только + - * / % имеют (чисто) математическое значение, но ясно понятный аспект применим и к другим (за исключением = , учитывая, что его часто путают с проверкой равенства ).

Лучшая конструкция для сравнения <condition> ? <if-true> : <else> - это if _statement_, а не другие операторы. Хотя if определенно более подробный, это именно тот аспект, для решения которого предназначена тернарная операция (помимо того, что это истинное составное выражение, в отличие от if ).

Конечно, есть спектр краткости, но, как вы говорите, для согласованного согласования всех связанных операторов, предлагаемых, имеет смысл синтаксис на основе символов.

тем из нас, кто еще не сталкивался с этим неоднократно.

Что ж, надеюсь, это скоро изменится. 😁
Точка принята, но (а) синтаксис легко объясняется и имеет ту же концептуальную сложность, что и оператор if , и (б) повторное воздействие должно помочь с сохранением памяти.

@ mklement0 Как вы предлагаете адресовать ? как допустимый символ имени? Критическое изменение? Я считаю, что люди, использующие ядро ​​PowerShell, хорошо разбираются в PowerShell как таковом, и что дополнительный синтаксис (который существует в других языках почти 50 лет) не будет помехой. Они всегда могут использовать if/else если хотят большей многословности.

? - допустимый псевдоним только в командном режиме; во всех вариантах режима выражения это просто недопустимый символ в настоящее время. Столкновения нет.

Если вы попытаетесь ввести этот код, он просто выдаст ошибку:

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

Результат:

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

В его примере с нулевым замачиванием: $var?.maybenull() не заботится о том, что там стоит вопросительный знак, и если кто-то пытается быть чрезмерно сжатым, его троичность сломается.

Извините, это в основном обсуждалось в другом выпуске, поэтому я не думал, что вы имели в виду это.

Сможем ли мы исключить то, что это действительный символ имени переменной, зависит от команды PS, но я склонен придерживаться мнения, что предотвращение того, чтобы он считался символом имени переменной по умолчанию, не сильно повлияет. Не думаю, что когда-либо видел, чтобы кто-нибудь действительно использовал ? как часть имени переменной.

@ vexx32 Да, я должен поднять это там. Это могло бы иметь дополнительные последствия, если бы также не было осторожно с областью видимости (хотя это уже видно в раскрытиях строк, поэтому люди должны быть немного знакомы с этим):

$var = $test?$thing1:$thing2

но, возможно, я слишком сильно раскалываю волосы на острых углах для тех из нас, кто живет в скорлупе.

Исправлено:

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

@ mklement0 - я не обязательно согласен с:

Лучшая конструкция для сравнения?:to - это оператор if, а не другие операторы. Хотя if определенно более подробный, это как раз тот аспект, для решения которого предназначена тернарная операция (помимо того, что оно является истинным составным выражением, в отличие от if).

В частности, тернарный оператор существует потому, что C / C # - это языки, ориентированные на инструкции, но для которых необходимы условные выражения.

В языках, ориентированных на выражения (например, F # или Rust), нет краткого синтаксиса, поскольку он считается ненужным. Я думаю, что это старое обсуждение Rust, удаляющего тернарный оператор, интересно.

В Rust мне очень нравится использование оператора ? для обработки ошибок. У меня нет конкретного предложения использовать ? в PowerShell, но мне кажется, что ? лучше использовать для обработки ошибок, чем для условного выражения.

@ TheIncorrigible1 , @ vexx32 : Да, обработка нуля технически была бы критическим изменением, но, надеюсь , относится {...} / пробела перед ? для устранения неоднозначности, похоже, решает эту проблему.

@lzybkr :

В частности, тернарный оператор существует потому, что C / C # - это языки, ориентированные на инструкции, но для которых необходимы условные выражения.

Что ж, в PowerShell операторы управления потоком, такие как if являются _half_-выражениями; в _simple_ выражениях предложенная тернарная операция будет эквивалентна; в _nested_ не было бы:

$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

Потребность в $() / @() - это больше, чем просто неудобство синтаксиса: это имеет последствия для поведения и производительности.

Тем не менее, я _ хочу_, чтобы такие утверждения, как if и foreach были добросовестными выражениями (еще два примера того, что в настоящее время не работает: foreach ($i in 1..5) { $i } | Write-Output или foreach ($i in 1..5) { $i } > out.txt ).
Я не знаю достаточно, чтобы судить, _не могут ли они быть_, однако и / или есть ли проблема обратной совместимости.
См. Также: # 6817


Если бы if стало полным выражением в PowerShell, вы могли бы привести аргумент, который привел к удалению тернарного условного выражения из Rust: тогда он больше не _необходим_.

Однако моей мотивацией для этого предложения никогда не было _необходимости_ - оно было связано с краткостью, удобством и удобочитаемостью (визуальный беспорядок).


У меня нет конкретного предложения? в PowerShell, а вроде как? может лучше использоваться для обработки ошибок, чем для условного выражения.

Я думаю, что введение ? с принципиально иной семантикой, чем в C #, будет источником вечной путаницы.

Отдельно стоит обсудить улучшения в обработке ошибок PowerShell.

Если мы ищем краткую, но не интуитивно понятную альтернативу If / Then / Else, она у нас уже есть.

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

И это работает в выражениях.

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

@TimCurwick : Это кратко (и более неясно), но не эквивалентно: предлагаемое тернарное условное выражение будет _коротким циклом_ (точно так же, как выражение if ), тогда как ваш синтаксис неизменно оценивает _обе_ альтернативы.

Тем не менее, ваш синтаксис, безусловно, является лучшим из доступных в настоящее время, если вы знаете об указанном ограничении.

Что касается обсуждения того, как отображать тройные варианты выбора в PowerShell, рассматривал ли кто-нибудь вариант в том же формате, который используется в -replace / .replace() ?

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

или

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

Это дало бы понять, что оператор выполняет тернарное действие, буквально называя его тернарным . Он подробный, но краткий для написания, и он использует существующее общее поведение -operator $first,$second , поэтому он должен быть знаком для пользователей PowerShell с любым опытом.

🤔 это могло бы сработать, но было бы более неудобно, чем любая из предложенных альтернатив. -replace работает таким образом, потому что он просто принимает фактический массив аргументов. .Replace() не управляется командой PS - это метод класса .NET System.String .

Если бы мы попытались использовать любой из этих синтаксисов, это означало бы либо метод ETS (что нормально, но имеет тенденцию добавлять небольшие накладные расходы производительности на создание объектов, к которым он должен быть прикреплен), либо с версией оператора вы предлагаете, мы не сможем легко использовать массив в качестве аргумента.

Без специального регистра такого оператора в парсере мы бы не смогли выполнить короткое замыкание. Тернарный синтаксис в других языках обычно существует, потому что вы _не хотите_ фактически оценивать оба варианта; время вычислений сокращается, если нужно оценивать только правильную ветвь, вместо того, чтобы полностью оценивать оба варианта (что может иметь некоторые значительные побочные эффекты).

А поскольку для этого уже потребуется специальный регистр, было бы более эффективно ввести для него новый синтаксис, чтобы свести к минимуму путаницу (было бы немного вводить в заблуждение иметь что-то, что выглядит как массив, но не может использоваться как один; это не поддерживал бы создание «массива» заранее и передачу его, например, как переменной). Тот факт, что аргументы метода уже немного противоречат синтаксису массива, часто уже вводит в заблуждение. Не думаю, что я захочу добавить в этот микс _third_ вариант поведения для запятых.

@ PowerShell / powershell-Committee подробно обсуждали это, мы не все согласны, но большинство согласны с тем, что есть смысл в наличии этого оператора и согласовании с синтаксисом C # с сохранением ?: поскольку ожидается, что большинство случаев использования будет быть от разработчиков C #. Эта функция будет экспериментальной в ожидании отзывов об использовании.

@ SteveL-MSFT Значит, эта функция продвигается в версии 7.0? Будет ли нарушена совместимость переменных, которые могут использовать ? в своем символе?

@ TheIncorrigible1: да, эта функция продвигается в PS7. Это не должно нарушать совместимость с использованием псевдонима ? . Есть опасения по поводу остроты зрения ? при взгляде на сценарий, пытающийся различить Where-Object и ternary , но мы посмотрим, что по этому поводу скажет пользователь. В общем, мы не ожидаем, что большинство пользователей будут использовать этот оператор, но это не должно помешать ему двигаться вперед.

@ SteveL-MSFT Я имею в виду переменные с именем $isValid? или аналогичным. Это действительные токены в текущей итерации PS.

@ TheIncorrigible1 :

Требование пробелов между первым операндом и ? решает эту проблему, как предлагалось ранее, и для меня это вполне разумное решение:

  • : _также требует пробела вокруг него, потому что что-то вроде $true ? $number:42 не будет работать, учитывая, что $number:42 будет _ как целое_ интерпретироваться как ссылка на одну переменную.

  • В то время как C # _позволительно_ разрешает true?number:42 , я не думаю, что нам нужно - или, действительно, можно - беспокоиться о совместимости на этом уровне. Я лично ценю краткость, но не в ущерб удобочитаемости; даже если бы я _ мог_ написать $true?$number:42 , я бы не стал.

(Обратная совместимость действительно будет проблемой, когда (подсказка, подсказка) мы реализуем нулевой условный доступ . Вседозволенность PowerShell в отношении имен идентификаторов обычно проблематична, как недавно утверждал @KirkMunro , но этот корабль отплыл )

Да, я думаю, что оставить требование пробела разумно. В конце концов, это и так достаточно лаконично. 😁

Прототип изо всех сил пытался разобрать числа с ? и : по-разному в контексте тернарного оператора (когда мы знаем, что ожидаем выражение). Таким образом, вы можете писать такие вещи, как ${isWindows}?12:47 .
Такие числа, как 123? или 1:23 , сегодня токенизируются как общий токен, что совершенно бесполезно в случае, когда мы знаем, что ожидаем выражение.

Для переменных нет никаких изменений в том, как ? или : могут использоваться для имени переменной, поскольку переменная является выражением.

Хорошее замечание, @ daxian-dbw; Я забыл, что {...} можно использовать для разрешения любой неоднозначности границ имен переменных, поэтому я полагаю, что игроки в гольф могут использовать что-то вроде ${isWindows}?${number}:47

Можем ли мы закрыть это сейчас?

Закрыть через # 10367

Была ли эта страница полезной?
0 / 5 - 0 рейтинги