Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

String equality is broken #4

Open
zeen opened this issue Jun 27, 2013 · 5 comments
Open

String equality is broken #4

zeen opened this issue Jun 27, 2013 · 5 comments
Assignees

Comments

@zeen
Copy link

zeen commented Jun 27, 2013

All strings are separate copies, so '==' checks break.

e.g.,

private function test() {
    var x = "hello";
    var t = (x == "hello");
    return t ? "Good" : "Bad";
}

generates this Objective-C:

- (NSMutableString*) test{
    NSMutableString *x = [@"hello" mutableCopy];
    BOOL t = x == [@"hello" mutableCopy];
    return ( (t) ? [@"Good" mutableCopy] : [@"Bad" mutableCopy]);
}

i.e., it returns Bad, because both instances of "hello" are separate copies, and '==' is false.

The fix for this would either be string interning, or using NSString.isEqualToString.

@ghost ghost assigned cristibaluta Jun 29, 2013
@cristibaluta
Copy link
Owner

I used isEqualToString, let me know if works for you. You might get some weird strings printed, they are part of the debugging and didn't cleaned all of them. What was the other way? I forgot it but might be useful.

@zeen
Copy link
Author

zeen commented Jul 1, 2013

isEqualToString works, but fails in some cases. s == null for example fails with a crash. This gets a little complicated if you take nulls into account, because if either operand is null, it'll crash when you call isEqualToString.

a==b should perhaps translate to (a==b||(a!=null&&b!=null&&a.isEqualToString(b)). Messy. != is the the inverse.

Also, this fails to work in any case:

var a:Dynamic = "x";
var b:Dynamic = "x"; //assume this is a different pointer
a == b // will fail in hxobjc because types are dynamic, will succeed in other haxe backends because strings are interned

Maybe implement == for Dynamic types as a function?

function ==(a:Dynamic, b:Dynamic) {
  if (a == b) return true;
  if (a == null || b == null) return false;
  if (a respondsToSelector:@selector(equals:))
   return [a equals:b];
  return false;
}

Then strings can implement equals:. Another options would be type checks for strings.

I think I should describe string interning. Interning basically means all strings get the same pointer. The system keeps a set/hashtable or strings, and new string if it exists in that table, is taken from that table, if it doesn't exist, then is put into that table. This way, two strings with the same content will always have the same pointer. Most modern languages do this, e.g., Java, Javascript, ActionScript, etc. In Java this is explicit (String.intern is an actual function, and Strings and other types have an obj.equals(obj2) function too). Not sure if you want to go this far or not.

Wikipedia has a good description: http://en.wikipedia.org/wiki/String_interning

@zeen
Copy link
Author

zeen commented Jul 1, 2013

Apparently there's an NSObject.isEqual() too.

@cristibaluta
Copy link
Owner

Do you know anything about C strings? I think they cannot be compared with == either, but chars seems they do. We need to think of how to implement the switch statement as well because we cannot switch on a NSString. I need to see what cpp is doing with strings.

@zeen
Copy link
Author

zeen commented Jul 2, 2013

It looks like the correct way to check equality for Objective-C objects is ((x == y) || [x isEqual:y]). This works even if x and y are nil.

I'm well experienced in C/C++, but haven't looked at the Haxe cpp backend. Will try to check it out.

Regarding the switch statement, you can't use NSString in a C switch. Switch in C requires compile time integer constants. You have to reduce it to if-elseif-else statements instead.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants