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 6 and 5 and type the answer here:
  • Post
  • I like that PowerShell lets me mine data quickly. I don't have to think about case.

    $_.Ticker -match 'ibm'

    I'd prefer consistency and fix scripts that had issues.

    Otherwise I have to keep lots of rules in my head depending on the type of data I am comparing.

  • I came across this post looking for something entirely different. Truth be told I have not used PowerShell yet!

    This clearly presents as a bug and should be fixed. I empathise with the decision that needs to be made, however if it's left as is then the problem will be forever recorded in history as one of those PowerShell peculiarities that should have been fixed long ago. You'll end up inconveniencing more people as the adopted userbase expands.

  • Feel it should remain as it is:

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

    False

    Since this is surely True, that 'a' and 'A' are not equivalent ...

    Regards

    Andy

  • IMO, it is a bug and should be fixed. The following currently returns true:

     'a' -eq [char]'A'

    and this returns false:

     'a' -ceq [char]'A'

    So apparently the [char] casting only matters on the left side of the equation? I would expect it to work the same regardless of where I do the casting.

  • I think that it should be fixed.

  • @Andy:

    "Since this is surely True, that 'a' and 'A' are not equivalent ..."

    yes - I didn't make the point well (I've now updated the article).  The problem is that this is ALSO the case when you use -IEQ

    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) >

    jps

  • I say "fix" it.

    As a developer, I don't think it's really a bug to compare int values ... particularly when you're forcing the comparison of CHAR instead of string. You have to be really deliberate to get a char in PowerShell, so it should be obvious...  and my first inclination was to say leave it, but ...

    If you leave it, then the only option people have to get a case INsensitive comparison is a rather expensive conversion to strings ... whereas if you fix it, we can always deliberately say -ceq ...

    Also, consider the inconsistency of

    PS> [char]$c = "a"

    PS> switch($c) {

    >> "A" { "Big A" }

    >> "a" { "Little A" }

    >> }

    >>

    Big A

    Little A

    PS> $c -eq "A"

    False

    ... that's really trippy :)

  • I can understand the dilemma, but my preference would be to move to the more readily apparent idiom where [char]'a' -ieq 'A' results in True.

    In a lower-level language, I could be more comfortable arguing that the v1 behavior is of value.  However, in PowerShell I've found such constructs to be more of a hindrance than produing more understandable and readable code.  Additionally, the fix for scripts written to make use of this issue is trivial (a simple cast to [int] will replicate this behavior).

    If the v1 behavior is allowed to remain, I would strongly urge for the removal of the -ieq operator for char, as it no longer would apply.

  • Jeffrey,

    Compliments on the great product, with Powershell we really get the sense of power,

    now I always feel I can do the things I need to do, when before we regulary got stuck or had to fall back to calling 3rd party tools or creating awkward workarounds!

    My opinion about this issue:

    It's a bug, so it's probably better fixed in v2.0 then in version v5.0, and there will be lots more scripts broken by that time.

    It would probably help to document the change really well in the release notes.

  • If you want to fix it, make sure it is consistent.

    I would prefer to have [char] 'a' -eq 'a' being FALSE as [char] and [string] are like apple and pineapple ;-)))

  • Its a bug its need fixing. I do agree with an earlier statement that if you don't fix it, it will haunt Powershell during its lifetime.

    Better to fix it now v2 than i v3 :-)

  • I find it hard to imagine that this behavious is something someone relies on. After all, it's easily worked around and thus I am strongly in favour of fixing it. As Adrian already pointed out, left this way it would be a language nightmare for the sake of compatibility just as many things in cmd are (and those are often a pain to work with).

    Oh, and it should be 'stakeholder' in the article, not 'stackholder', I think :-)

  • As mentioned before, both -eq and -ieq has the same output for those four:

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

     False

    'a' -eq 'A'

     True

    [char]'a' -eq 'A'

     False

    'a' -eq [char]'A'

     True

    <Ups, I dived deep into this - have full screen of -eq, -ieq, ceq :)>

    Frankly - I am a PowerSheller short time and till now haven't trouble with comparison (it worked as I expected). As I now tested really a lot of comparison, for me current state is OK. Maybe except points three and four in my examples - this is for me strange.

  • Fixing bugs is the best long term strategy. If I had (in some bizzare mental state) relied on this bug in a script then I would probably like the opportunity to address it.

    Knowing the details of the bug, surely it wouldn't be too much of a stretch to create a crawler to itterate through scripts and identify where this fix might break something.

    cheers (keep up the good work)

    n

  • Clearly a bug and should be fixed.

    For the justification I will say that Powershell is still a very young language, and while this may create a couple of headaches right now.....imagine what it would be like if this stays the same for YEARS and becomes a quirk of the language.

Page 1 of 5 (61 items) 12345