Decision Input Requested: -EQ with Characters

Decision Input Requested: -EQ with Characters

  • Comments 61

We are struggling with whether or not to make a change in our comparison operators and would like feedback from the community.

Here is the documentation about comparision operators: 

 All comparison operators are case-insensitive by default. To make a comparison operator
 case-sensitive, precede the operator name with a "c". For example, the case-sensitive
 version of "-eq" is "-ceq". To make the case-insensitivity explicit, precede the operator
 with an "i", for example, the explicitly case-insensitive version of "-eq" is "ieq".

Here are examples of the current -EQ semantics:

PS> "a" -eq "A"
True
PS> [char]'a' -eq 'a'
True
PS> 2 -eq 2
True

Notice that -EQ works with Strings, Chars, and INTs (and lots of other things). 

Now for the headache: 

PS> [char]'a' -eq 'A'
False
PS> [char]'a' -ieq 'A'
False

<Update:  Notice that you get FALSE whether you use -eq (EQUALS) or -ieq (CASE INSENSITIVE EQUALS) >

What is happening here is that CHARs are being treated like INTs and not like STRINGs.  In our bug triage, we the feeling was that this was clearly a bug and should be fixed but someone pointed out that this if a script made use of these semantics, fixing the bug would break that script.  There are 2 things to say about that:

  1. Whenever you fix a bug, you run the risk of breaking a script.
  2. We are committed to making V2 useful and compatible with V1.

So you see the rub.  We'd like your help and input on this decision.  I'm fine getting feedback on the "general principles" of the issue - understanding how you think about these issues is very helpful to us.  That said, I'm also keenly interested in comments about the specifics of this problem. If we make THIS change, do you think it will break scripts?  If so, should we fix this anyway or not?

We struggled with this decision and had lots of back and forth on this and could go either way.  In the end, we decided that a key stackholder wasn't in the room:  YOU. 

Please opine.

<UPDATE:  BTW 10,000 apologizes for this situation in the first place.  I should have started with that.>

Jeffrey Snover [MSFT]
Windows Management Partner Architect
Visit the Windows PowerShell Team blog at:    http://blogs.msdn.com/PowerShell
Visit the Windows PowerShell ScriptCenter at:  http://www.microsoft.com/technet/scriptcenter/hubs/msh.mspx

Leave a Comment
  • Please add 7 and 8 and type the answer here:
  • Post
  • It might break existing scripts but fix it anyway.  

  • Fix it.

    This bug breaks one of Powershell's great strengths, which is it's consistency.

  • Like most people, I vote for fixing it.  Backwards compatibility is nice in the short-term but it's pure evil in the long-term.  There's no reason why everyone should have to live with this bug *forever*.  Just take the hit now and fix it.

    Of course, I'm not the one who's going to have broken scripts, so take that for what it's worth.  :-)

  • As some people have pointed out (and I think this should be made clearer in the post, Jeffrey), we have a huge inconsistency here:

    PS> 'a' -eq [char]'A'

    True

    PS> [char]'A' -eq 'a'

    False

    If A equals B, B should always equal A, no matter what. So it IS a bug and it SHOULD be fixed.

    Now comes the second part: in .NET, when you compare a Char with a String, the result is always False. I agree with Domdomz when he says that [char] and [string] are like apple and pineapple. Even though Powershell does and should continue doing a lot of things under the hood to make things easier for everyone, I don't think it should automatically compare Chars with Strings (unless someone comes up with a good example of why that would be useful).

    So, my opinion is: it MUST be fixed, but String and Char comparisons should return False.

  • I say "fix it!"  People are using the example "A" -eq "a", but we know very well that's not how the comparison will happen in real life.

    It'll be more like:

    $fileA -eq $FileB

    where $fileA is = "rundll.exe" and $FileB is

    "RUNDLL.EXE".

    And *that* will be confusing, the sort of thing that Linux advocates will crow about for years.

  • The argument that a [char] and a [string] should always be unequal is absurd in context - would you argue that an [int] and a [double] are similarly dissimilar, and that:

    1.0 -eq 1

    should be false?  What about comparing a [double] and a [string]?

    "1" -eq 1.0

    IMHO, both [char] and [string] are different forms of [text], and thus case insensitive amd sensitive comparisons should be valid.

  • Dang...a ton of comments on this post.

    I fall on the "[char]'a' -ieq 'A'

    This should eval to TRUE since it's what 90% of administrative scripters (the main target audience) would expect." side of the fence.

    Fix it.

  • Yep, fix it.  Just make sure that this behavior change is well documented in the release notes.  It might be nice to have a PowerShell.exe switch that would flag use of changed functionality within a script that could potentially break the script.

  • Yes, Fix it...

    With a "big" warning in release notes ;). It's most important to fix bug that to be compatible with old script that take advantage of a bug. I think the most important is that the "work around" found by some of us (if any) still works...

    Regards!

  • I'm not trying to start a flame war here, so let's all relax =).

    Let me explain why I think a [char] and a [string] comparison should return false...

    1- Powershell is built upon .NET and that's how it works there.

    "But, but... Powershell is a scripting language and it doesn't have to follow all the stupid rules of this lower level platform! It should make things easier for the scripters out there!"

    Which I would reply to with:

    2- Yes, you are right. Powershell should make things easier for everyone (and it does), but making chars equal to strings would not simplify things, in my opinion. Visually, it is compelling to say: [char]'a' is just like 'a', of course they should be equal... They represent the same thing.

    But chars don't appear in code like that. They are almost exclusively the return of some method call, like 'string'.ToCharArray(). The only counter intuitive comparison a scripter could face (at least that I can think of) is the "[char]'a' -eq 'a'" example, which, as I said, probably won't be seen in real world scripts.

    3- Powershell already treats [char] and [string] differently. When they tried to do too much (making them equal), guess what happened? =)

    Let's say 'a' -eq [char]'a' should return $True. In the following code, what should the last line return?

    PS> $string = 'a'; $char = [char]'a'

    PS> [int]$string -eq [int]$char

    In a perfect world, chars and strings should be equal, and all design decisions are easy... But Powershell IS built upon .NET, so maybe it should follow some of their rules, when it's not possible to break them.

  • Fix the bug.  If it's not too awkward, provide a switch that can be configured or set in a script for backwards compatibility.

  • Bruno,

    Powershell is fundamentally different than C# in the way it 'auto converts' types.  Making Powershell more 'internally consistent' is what makes sense for Powershell.

    It would have been wrong for C# to have worked the proposed Powershell way.  It's not 'internally consistent' with strong typing.

    Second, language semantics are different than "built on .Net".  There are considerable differences between VB.net and C# and both are built on .Net

  • Please fix it!  The sooner the better.

    You're worried about the number of scripts out there today that could be broken, but think how many more scripts there will be in 10 years.  Save the future from the present!

  • Fix it.

    Better to fix a few scripts now, that to live with the inconsistency for eternity.

  • I vote fix it. It's still pretty early in the grand scheme of things.

Page 3 of 5 (61 items) 12345