Note: This may be an exotic scenario that is easily avoided (no reason to ever use return
this way), but I just came across it on Stack Overflow, and the behavior is surprising and unhelpful.
# The assignment is *ignored* due to `return`, and the output goes straight to the success output stream.
$var = return 'foo'
$var | Should -BeExactly 'foo'
The test should succeed.
The test fails, because the assignment is ignored (the variable isn't even created) due to use of return
.
The output goes straight to the success output stream and therefore prints to the display here.
PowerShell Core 7.1.0-preview.5
The RHS is executed before any assignment happens. Works the same as any other flow control statement like $a = throw
/$a = continue
. Probably should have been a parse error when assignments started allowing statements on the RHS, though I'm not sure it'd be worth doing now. (Edit: wasn't a thing) (Edit 2: I don't know what's real anymore) Maybe a PSSA rule?
As far as I know, assignment has always allowed full statements on the RHS. Because of this arrangement of the grammar, it would be very difficult, if not impossible, to turn this into a parse error. If nothing else, it would turn the RHS of assignments into a strange and confusing subset of the allowed statement grammar.
I'd say this is most like the old func_call(i++, i++)
in C. It's syntactically allowed, but semantically not a good idea.
Thanks, @SeeminglyScience and @rjmholt - I'm personally happy with a "won't-fix" / "as-designed" classification , but I wanted the potential pitfall recorded.
Perhaps a candidate for the docs wiki?
I've updated the SO answer based on the feedback, so I'm happy to close this.
As an aside, @rjmholt: there is a second answer there that summarizes (and links to) our discussion in #10967 (using statements in pipelines / as expressions).
As far as I know, assignment has always allowed full statements on the RHS.
I could have sworn there was a time back in the dark ages of v2 or 1 where you couldn't have an if
statement on the RHS... Maybe I'm thinking of return
statements? 馃し anyway thanks for the correction 鉂わ笍
I could have sworn there was a time back in the dark ages of v2 or 1 where you couldn't have an if statement on the RHS
@SeeminglyScience You are right, and it was relaxed to allow statement on the right hand side of assignment in v3.
A parsing error is possible by semantic checks, but may not be worth the effort.
Hmm... I just tried $var = if ($true) { 'yay' }
and $var = foreach ($i in 1..10) { $i }
in v2, and it worked.
However, something related is indeed broken, all the way up to v5.1 (fine since v6), although the scenario is very specific:
# Breaks in *Windows PowerShell* - OK in PowerShell Core.
@{
Foo = if ($true) { "yes" } # Value is an `if` statement that LACKS AN `else` and there's NO OTHER ENTRY on the SAME LINE
Bar = 'Baz' # !! Any key AFTER triggers the error
}
@SeeminglyScience You are right, and it was relaxed to allow statement on the right hand side of assignment in v3.
A parsing error is possible by semantic checks, but may not be worth the effort.
See that's what I thought but then:
Hmm... I just tried
$var = if ($true) { 'yay' }
and$var = foreach ($i in 1..10) { $i }
in v2, and it worked.
I tried it too with -verison 2
and it worked. I know there are some scenarios where -version 2
doesn't work exactly the same but I wouldn't have thought this would be one. You know if it was back ported? or maybe a change between 1 and 2?
At least I know I'm not crazy 馃榾
I know there are some scenarios where
-version 2
doesn't work exactly the same
That's good to know (-version 2
is what I used too) - would have never occurred to me.
That's good to know (
-version 2
is what I used too) - would have never occurred to me.
Full disclosure, that's what I've heard. I don't remember anything specific or having ran into anything personally (though I also don't use it super often) so ymmv
Hmm... I just tried
$var = if ($true) { 'yay' }
and$var = foreach ($i in 1..10) { $i }
in v2, and it worked.
Ah, then I must remember it wrong. It could be a v1 -> v2 change. I doubt it would be ported back to v2 if it was done in v3, as v3 was a huge rewritten of a lot stuff.
However, something related is indeed broken, all the way up to v5.1 (fine since v6), although the scenario is very specific:
I think this one was fix by https://github.com/PowerShell/PowerShell/pull/7002
Thanks, @daxian-dbw.
Can you tell us definitely if there can ever be a difference between running a later version with -version 2
and a stand-alone v2 version and, if so, what those difference are?
I don't think there is any difference between running a stand-alone v2 version and running powershell -v 2
.
The reason to have powershell -v 2
was that there were breaking changes introduced in v3 and we needed a way for users to keep using v2 without worrying about anything broken. So by definition, it shouldn't allow any difference.
I believe the v2 assemblies that are in-box for powershell -v 2
to work were just a redistribution of those from a stand-alone v2 version. So, more precisely, there shouldn't be any difference code-wise.
Most helpful comment
The RHS is executed before any assignment happens. Works the same as any other flow control statement like
$a = throw
/$a = continue
. Probably should have been a parse error when assignments started allowing statements on the RHS, though I'm not sure it'd be worth doing now.(Edit: wasn't a thing)(Edit 2: I don't know what's real anymore) Maybe a PSSA rule?