Pipes in powershell are just as powerful as in bash.
Every curly braces pair is a lambda function with a single parameter $_.
You can approach powershell very functionally and the abstractions work fine.
It is however a minefield of pitfalls.
Obscure error handling at the root script. Always run code at a main function that is called in the root script.
Permissive undefined variables and parameters access.
Unwinding nested attributes by referring to it at the root object level: what if you need a variable attribute from an object but the attribute collides with a built in method?
Truthy and equality are not interchangeable. -eq and Object.Equals produces vastly different results, due to the first not being type safe.
Some functions are sintactically similar to flags and parameters: -join.
Case insensitivity. Seriously...
All in all, if you are mindful of the pitfalls, use Set-StrictMode early on and don't run code at the script root, you are fine. Better than bash. A well written poweshell code is in my opinion way more readable and maintainable by than a well written bash code, despite its shortcomings.
However both of them don't come close to what python is in terms of type safety, error handling, legibility, flexibility and maintainability, even for system scripting.
My favorite is that functions don't actually have return statements.
A return is just an exit for the function. If you try to assign the output of a function to a variable, it will essentially be a string containing whatever is printed to the console throughout the function's duration.
No, that's misleading. The result is not typecast to string, it's not combined into a single string, many outputs become an array. And it's not whatever is printed to the console, it's whatever was sent to the pipeline output. Printing to the console is separate in PowerShell. Unlike in Linux world where the main way appears to be abuse of stderr for things which are informational and not errors, PowerShell has many output streams, and only one of them is the output of a function. e.g.
function test {
"hello"
5
write-host "world"
}
$result = test
$result contains "hello",5 the output of the function and 5 is still typed as an integer - not string and not a single string - and the console prints "world".
And it does this to make it work like a Unix shell, because if you write a command and get some output, then want to batch some commands together in a function and get no output except what you explicitly "return", that would be annoying.
> "functions don't actually have return statements"
They do actually have return statements (for control flow).
(And if you make classes with methods, they have traditional programming language features - called with parens, lexical scope, return statement controls the return value).
Oh Man, that can also cause a lot of issues. If you call a function that has a return value but you don't actually need it, like invoke-webrequest, but you use an explicit return statement right thereafter things go haywire. I have yet to produce a proof of concept to illustrate this issue, but I came across this and it actually overwrites my return statement with the orphaned return value from the invoke method. Took me ages to figure out what was wrong, because debugging the application I could see inside the function that the variable I was returning had the expected value, but what was being bound to the outside was something completely different
Every curly braces pair is a lambda function with a single parameter $_.
You can approach powershell very functionally and the abstractions work fine.
It is however a minefield of pitfalls.
Obscure error handling at the root script. Always run code at a main function that is called in the root script.
Permissive undefined variables and parameters access.
Unwinding nested attributes by referring to it at the root object level: what if you need a variable attribute from an object but the attribute collides with a built in method?
Truthy and equality are not interchangeable. -eq and Object.Equals produces vastly different results, due to the first not being type safe.
Some functions are sintactically similar to flags and parameters: -join.
Case insensitivity. Seriously...
All in all, if you are mindful of the pitfalls, use Set-StrictMode early on and don't run code at the script root, you are fine. Better than bash. A well written poweshell code is in my opinion way more readable and maintainable by than a well written bash code, despite its shortcomings.
However both of them don't come close to what python is in terms of type safety, error handling, legibility, flexibility and maintainability, even for system scripting.