Skip to content

Allow advanced functions to only return objects to the pipeline explicitly #3669

Closed

Description

@SteveL-MSFT

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.

Activity

  1. added this to the milestone on May 1, 2017
  2. powercode commented on May 1, 2017

    @powercode
    Collaborator

    I think that will prevent a lot of bugs

  3. lzybkr commented on May 1, 2017

    @lzybkr
    Contributor

    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.

  4. bergmeister commented on May 25, 2018

    @bergmeister
    Contributor

    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

  5. markekraus commented on May 26, 2018

    @markekraus
    Contributor

    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
    
  6. iSazonov commented on May 26, 2018

    @iSazonov
    Collaborator

    Breaking change.

  7. markekraus commented on May 26, 2018

    @markekraus
    Contributor

    Ilya (@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.

  8. iSazonov commented on May 26, 2018

    @iSazonov
    Collaborator

    Dot-sourcing can be break.

  9. markekraus commented on May 26, 2018

    @markekraus
    Contributor

    Ilya (@iSazonov) I'm not sure I follow how that would break dot sourcing. Can you elaborate?

  10. iSazonov commented on May 26, 2018

    @iSazonov
    Collaborator
    using strict return
    
    . .\function.ps1

    Seems function.ps1 may not work as expected.

  11. markekraus commented on May 26, 2018

    @markekraus
    Contributor

    Maybe. The original proposal from Steve Lee (@SteveL-MSFT) was to add a property to CmdletBinding.

  12. lzybkr commented on May 29, 2018

    @lzybkr
    Contributor

    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.

  13. jez9999 commented on Jul 4, 2018

    @jez9999

    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.

  14. rkeithhill commented on Jul 4, 2018

    @rkeithhill
    Collaborator

    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
    
  15. jez9999 commented on Jul 4, 2018

    @jez9999

    Quite. It's a convenience that saves no bytes at all, and looks misleading.

  16. jantari commented on Jan 17, 2022

    @jantari

    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:

    I feel like PowerShell could just reuse the C# syntax yield return for explicitly passing an object to the pipeline without exiting the function like a bare return would.

    I would still love to see this feature: [CmdletBinding(ExplicitReturn)] on functions and then only pass objects on to the pipeline with yield return or return keywords. As Steve Lee (@SteveL-MSFT) said it's been a long standing source of frustration for new and old PowerShell users, could this be looked at again and evaluated for the roadmap for this year or so?

  17. microsoft-github-policy-service commented on Nov 16, 2023

    @microsoft-github-policy-service
    Contributor

    This issue has not had any activity in 6 months, if this is a bug please try to reproduce on the latest version of PowerShell and reopen a new issue and reference this issue if this is still a blocker for you.

  18. microsoft-github-policy-service commented on Nov 16, 2023

    @microsoft-github-policy-service
    Contributor

    This issue has not had any activity in 6 months, if this is a bug please try to reproduce on the latest version of PowerShell and reopen a new issue and reference this issue if this is still a blocker for you.

  19. microsoft-github-policy-service commented on Nov 16, 2023

    @microsoft-github-policy-service
    Contributor

    This issue has not had any activity in 6 months, if this is a bug please try to reproduce on the latest version of PowerShell and reopen a new issue and reference this issue if this is still a blocker for you.

  20. jantari commented on Nov 16, 2023

    @jantari

    This is still something I'd very much like to see and I also stand by the idea of borrowing yield return as a new statement.

  21. microsoft-github-policy-service commented on Nov 24, 2023

    @microsoft-github-policy-service
    Contributor

    This issue has been marked as "No Activity" as there has been no activity for 6 months. It has been closed for housekeeping purposes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Issue-Enhancementthe issue is more of a feature request than a bugResolution-No ActivityIssue has had no activity for 6 months or moreWG-Languageparser, language semantics

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions