One concern I've heard from several people is that they are surprised that anything emitted (generally accidentally because they didn't set or pipe to $null) within the function shows up in the pipeline. Although is can be a powerful construct, it can also cause confusion to developers familiar with other language semantics for return. PowerShell classes does support return to explicit return objects, but we should consider perhaps adding a property to the CmdletBinding attribute so that objects not returned are swallowed and only emitted if explicitly returned.
I think that will prevent a lot of bugs
One proposal I had was to add something like:
using strict return
At the top of the script. We could also enable lexical scoping in a similar manner.
Makes sense but only if a function with this new attribute does not prevent Windows PowerShell from being able to parse/use such a function.
Being able to enforce the return type and prevent PowerShell from casting the type of returned object would be great as well
I like the idea of adding an option to make this possible. But, I also fear this will result in some really bad code for PowerShell. It will encourage users to ball things up and return them all at once instead of releasing them to the pipeline as created. That is the issue I see more commonly coupled with users who mistakenly think that return is the only place objects are emitted.
One design consideration would be to include the ability to return multiple objects explicitly to without the flow control aspect of return. for the sake of demonstration I will use emit as a keyword for this:
function Get-Stuff {
[CmdletBinding(ExplicitReturn)]
param ()
process {
# Not emitted
Get-ChildItem c:\
# emitted without flow control
emit 1
emit 2
# emitted and flow control sent
return 3
# Not executed
Get-Date
}
}
Get-Stuff
Result:
1
2
3
Breaking change.
@iSazonov How would this be a breaking change? So far everything discussed here is additive. instead of emit we could change return to accept a switch return -Continue $value or something.
Dot-sourcing can be break.
@iSazonov I'm not sure I follow how that would break dot sourcing. Can you elaborate?
using strict return
. .\function.ps1
Seems function.ps1 may not work as expected.
Maybe. The original proposal from @SteveL-MSFT was to add a property to CmdletBinding.
using is this context should be lexical - applying only to the file it appears in. If using affected something dot sourced, that should be considered a bug.
And even if it doesn't, one could say it's not a breaking change - you had to opt-in with new syntax.
Can I ask a dumb question? It seems like the design goal of PowerShell was "output stuff to the pipeline and then stop processing". So why does return $someValue even exist as valid syntax? It makes it look an AWFUL lot like you are just returning $someValue. Wouldn't it make more sense to say, if you want to just output anything emitted to the pipeline, say return. If you want to swallow that and just output a certain value, say return $someValue? Right now it seems like some weird hybrid where it outputs everything that was emitted previously AND $someValue. I'd be interested to know the thinking that went into that decision.
return allows you to return early from a function/scriptblock. It's a way to alter the normal flow of control like break and continue do inside a loop.
As a "convenience", return also allows a value to be output. Essentially return $someValue is the equivalent of:
$someValue
return
Quite. It's a convenience that saves no bytes at all, and looks misleading.
Most helpful comment
One proposal I had was to add something like:
At the top of the script. We could also enable lexical scoping in a similar manner.