PowerShell return
Aug. 30th, 2018 11:16 pmТо, как повершелл ведет себя с возвратом из функций меня СУКА БЕСИТ.
Языки здорового человека либо строго типизируют возврат (C; внезапно bash), либо никак не типизируют (Python). В повершелле можно указать тип возврата директивой OutputType... но она ни к чему не обязывает, я могу указать String и вернуть int.
Далее, языки здорового человека (C, Python) имеют команду return - вот что ей дал, то функция и вернет. Языки здорового человека со странностями (VB, емнип Pascal) это делают путем присвоения значения возврата "имени функции". Шелл здорового человека (bash) умеет возвращать только код возврата - но там функции могут писать в stdout, для перехвата которого есть штатный конструкт (где-то здесь порылся срач между $() и ``).
Сраный повершелл возвращает все, что кем угодно было выведено в stdout ПЛЮС то, что вернули return - этакая ужасная помесь процедурного языка и шелла. Если было несколько такого дела, возвращается массив, элементами которого являются выводы - даже если этот вывод $null. Вот только что на выходе из функции, которая должна возвращать НИЧЕГО, я поимел @($null, $null) и с горящей задницей искал, откуда это лезет. Нашел и пофиксил, конечно, но осадок остался.
Мораль сей басни такова: если вы пишете на PSH не в шелл-стиле и не в BEGIN-PROCESS-END стиле, а в старом добром процедурном (если вы в анамнезе решеточник, питонист или, оужас, сишник), то внимательно следите за выводом. Вызов любого командлета или функции, которые хотя бы теоретически могут что-то вернуть, но который вам нафиг не нужен, должен быть либо присвоен мусорной переменной, либо отправлен конвейером в Out-Null. Иначе дебаггинг гарантирован.
Да, чтобы два раза не вставать, ну вот на хрена запилено пицот (ладно, 5 или 6) потоков вывода вместо старых добрых stderr и stdout, если нельзя сделать | Out-Verbose или | Out-Error , а только Write-Error или Write-Verbose - и это при том, что "конвейером объектов" размахивают все адепты.
Языки здорового человека либо строго типизируют возврат (C; внезапно bash), либо никак не типизируют (Python). В повершелле можно указать тип возврата директивой OutputType... но она ни к чему не обязывает, я могу указать String и вернуть int.
Далее, языки здорового человека (C, Python) имеют команду return - вот что ей дал, то функция и вернет. Языки здорового человека со странностями (VB, емнип Pascal) это делают путем присвоения значения возврата "имени функции". Шелл здорового человека (bash) умеет возвращать только код возврата - но там функции могут писать в stdout, для перехвата которого есть штатный конструкт (где-то здесь порылся срач между $() и ``).
Сраный повершелл возвращает все, что кем угодно было выведено в stdout ПЛЮС то, что вернули return - этакая ужасная помесь процедурного языка и шелла. Если было несколько такого дела, возвращается массив, элементами которого являются выводы - даже если этот вывод $null. Вот только что на выходе из функции, которая должна возвращать НИЧЕГО, я поимел @($null, $null) и с горящей задницей искал, откуда это лезет. Нашел и пофиксил, конечно, но осадок остался.
Мораль сей басни такова: если вы пишете на PSH не в шелл-стиле и не в BEGIN-PROCESS-END стиле, а в старом добром процедурном (если вы в анамнезе решеточник, питонист или, оужас, сишник), то внимательно следите за выводом. Вызов любого командлета или функции, которые хотя бы теоретически могут что-то вернуть, но который вам нафиг не нужен, должен быть либо присвоен мусорной переменной, либо отправлен конвейером в Out-Null. Иначе дебаггинг гарантирован.
Да, чтобы два раза не вставать, ну вот на хрена запилено пицот (ладно, 5 или 6) потоков вывода вместо старых добрых stderr и stdout, если нельзя сделать | Out-Verbose или | Out-Error , а только Write-Error или Write-Verbose - и это при том, что "конвейером объектов" размахивают все адепты.
(no subject)
Date: 2018-08-31 01:05 pm (UTC)Вот, смотри:
function foo { write-output "xyzzy" return "plugh" } $foo = foo $foo xyzzy plugh(no subject)
Date: 2018-08-31 03:17 pm (UTC)Get-Location
return "plugh"
}
$foo = @(foo1)
cls
$foo[-1]
(но это я уже нагуглил) https://stackoverflow.com/questions/10286164/function-return-value-in-powershell/10288256
(no subject)
Date: 2018-09-03 10:37 am (UTC)Одна из задниц повершелла в том, что его явно делали с оглядкой одновременно на баш, питон и решетку (последнее и так было неизбежно в силу решеточности) и с обратной совместимостью с cmd. В результате ConvertFrom-Json вместо Hashtable выдает PSCustomObject (а вот питоновский json.load дает dict, что в моих приложениях удобнее), (@("123") | convertto-json | convertfrom-json) -eq "123", функции весь свой мусор выводят в вывод, curl сделали алиасом на Invoke-WebRequest, сравнение у нас -ne, а не != и т.д. и т.п.
Короче, получилось нечто вроде бы похожее и вроде бы в чем-то совместимое по парадигме, но стоит увлечься, и ты выстрелил себе в ногу, потому что питоновская парадигма сменилась на баш, или наоборот, или еще как. Я не исключаю, что python-shell для линукса выглядел бы не менее коряво - но из всех языков, на которых я когда-либо писал (Basic/VB/VBA/VBScript, Pascal, C, Java, bash, awk, Python), PSH выглядит наиболее упорото.
Вот даже предлагаемое тобой оборачивание с точки зрения синтаксиса выглядит упорото. Получается, что если $foo не массив, то @($foo) работает как конструктор, а если массив, то как каст. Сравни с питоном: