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 2 and 1 and type the answer here:
  • Post
  • Hello everybody,

    I think you should fix it, but not the way you are suggesting. Strong typing inherently means to me that a char is NOT an int. A char is a char, and an int is an int. You can convert one to the other, but they are not the same. So [char]'A' -eq 65 should be false in my opinion (if it not even throws some kind of type mismatch error). Thus, [char]'a' -eq 'a' should be false also, as a char IS NOT a string, and never will be. The benefits of (very) strong typing extend well into the scripting world in my opinion.

    Best Regards,

    Stefan Falk

  • Fix this bug asap and change the file extension from ps1 to ps2. It is much easier to change the file extension than adding "reqires version 2" on each and every new script.

  • i say fix it, but have some sort of "strict" mode, or a function that can peruse a script and point out possible compatibility issues such as this.

  • [char]'a' -ieq 'A'  should get fixed even if there are body of scripts coded to the old behavior.

    You can soften the blow with compiler modes or 'depricated' warnings.

  • Definitely fix it!  This is one of those issues that makes people like me use char objects a lot less (if ever) simply because they don't work as I would expect them to with the standard operators.

    If you do the right thing and fix this, please, please, please don't forget this: the contains operator is also broken for char arrays and should have a similar fix applied so that you can properly find out of a character array contains a specific character or not using case-sensitive and case-insensitive comparisons.  This is also broken and very inconsistent in PowerShell, enough so that I don't use character arrays anymore at all because of this issue in v1.

    [179] PS↑ C:\> [char[]]'abcde' -contains 'a'

    True

    [180] PS↑ C:\> [char[]]'abcde' -icontains 'a'

    True

    [181] PS↑ C:\> [char[]]'abcde' -ccontains 'a'

    True # this should be False

    [182] PS↑ C:\> [char[]]'abcde' -contains 'A'

    False # this should be True

    [183] PS↑ C:\> [char[]]'abcde' -icontains 'A'

    False # this should be True

    [184] PS↑ C:\> [char[]]'abcde' -ccontains 'A'

    False

    --

    Kirk Munro [MVP]

    Poshoholic

    http://poshoholic.com

  • Sorry, one typo in my last comment.  The # this should be False comment shouldn't be there.  Copy/paste bug. :P

    Anyhow, the point is the same regardless.  -contains needs the same attention for [char[]] as -eq does for [char].

  • My opinion: fix this anyway!

    If old scripts break one should always be able to run them using PowerShell V1. PowerShell V2 should have PS2 file extension anyway. Languages will always change.

    --

    greetings

    dreeschkind

  • Definitely fix it. Jaykuls 'switch' example provides a 100% convincing argument as I see it.

    If you don't fix it now more scripts will be written, thus increasing the surface area for pain when the issue resurfaces in the future.

    Just my $00.02

    Stuart

  • I absolutly agree with dreeschkind. Change the file extension to ps2 and fix the bug.

    I can't repeat it often enough: Change the file extension!

  • IMHO, this is a bug and should be addressed. If types are defined then you should get what you ask for:

    [char]'A' -ceq [int]65   [evaluates True](Valid)

    [char]'a' -ceq [int]97   [evaluates True](Valid)

    [char]'A' -ieq [char]'a' [evaluates False](Valid: 65 != 97)

    I agree with Bruno Gomes about if a=b then b=a. Which this example shows does not work here:

    [string]'a' -ieq [char]'A' [evaluates True]

    [char]'A' -ieq [string]'a' [evaluates False]

    However, both should evaluate as False as String and Char types should not be equal. And for that matter, the following should evaluate as false:

    [string]'a' -eq [char]'a' [evaluates True]

    [char]'a' -eq [string]'a' [evaluates True]

    If a script doesn't define types, then this is all that is required:

    'a' -ceq 'A' [evaluates False]

    'a' -ieq 'A' [evaluates True]

  • This should be fixed.  Chars should be chars, not some cute way to refer to an int.

    This looks like a holdover to the c language where just about everything could be interpreted as an int.  You don't intend PowerShell to become c, do you?  PLEASE say no.

    c was (is) a fine language for those who can handle it properly.  But, that doesn't mean every language that comes after must emulate it.  There are plenty of quirks in c that would be much better left behind.

    I repeat - chars should be chars with their own existence and behavior quite outside of any other data type.  Fix it and let the scripts break.  It's the right thing to do.

  • Fix it!

    I'm not sure if any user at all considered this as a feature and used it.

    If you're still worried about backward compatibility then put in an option to switch on a "1.0 compatibility mode", as a command line option or environment variable.

    This might be even more useful if there are other compatibility breaking changes in 2.0.

  • I don't think you should emphasize backwards compatibility in this case.

    If char 'a' and 'A' both are converted to the same integer something is contraintuitive anyway (I'd expect one to be 65 and the other 97 - flipping the 6th bit was the way to change case on ascii characters).

    If it break scripts then ship the 2.0 release with a clear warning that users should read the changelog and then maybe also ship a script that can browse a folder and find scripts that has the problem.

  • I say fix it as well.  Some people say that a char should never be the same as a string, but from an admin point of view that makes no sense.  How about the example:

    [char]'a' -ieq (([string]'A')[0])

    False

    (([string]'A')[0]).gettype()

    Name: Char

    A string can be referenced by the array operator, which in turn returns a Char. In this case I did not explicitly cast it as a Char, but still got a Char result from a String source.  So it doesn't make sense to me to say they can't be compared, especially when a char appears to be an element in a string.

  • Fix it. My opinion is do the right thing. If one thing is wrong, correct it.

Page 4 of 5 (61 items) 12345