Powershell: Allow advanced functions to only return objects to the pipeline explicitly

Created on 1 May 2017  路  14Comments  路  Source: PowerShell/PowerShell

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.

Issue-Enhancement WG-Language

Most helpful comment

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.

All 14 comments

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.

Was this page helpful?
0 / 5 - 0 ratings