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

Fix numeric == on room ver #1194

Merged
merged 1 commit into from
Feb 22, 2022
Merged

Fix numeric == on room ver #1194

merged 1 commit into from
Feb 22, 2022

Conversation

richvdh
Copy link
Member

@richvdh richvdh commented Feb 21, 2022

Room versions are strings, so we should use string operators.

Room versions are strings, so we should use string operators.
@richvdh richvdh requested a review from a team as a code owner February 21, 2022 18:58
Copy link
Contributor

@DMRobertson DMRobertson left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • Was this implicitly parsing $self->room_version as an int before?
  • Is there a way to mark $self->room_version as a string so that == 1 throws up warnings?
  • Is there a reference for == versus eq? I tried perldoc.perl.org but wasn't especially illuminated.

@DMRobertson
Copy link
Contributor

Oh, I missed the "go here" on that linked page. https://perldoc.perl.org/perlop#Equality-Operators is useful. It describes numerically equal and stringwise equal without really defining either. I suppose one shouldn't really be using either of these to compare e.g. arrays, hashmaps, objects etc then?

@DMRobertson
Copy link
Contributor

(I'm assuming the test failure is a flake here?)

@richvdh
Copy link
Member Author

richvdh commented Feb 22, 2022

  • Was this implicitly parsing $self->room_version as an int before?

Yeees.

So, the problem is that perl doesn't really distinguish between ints and strings. (no, really). There are "strings that only contain digits", and "strings that contain things other than digits". (There's some optimisation under the hood to make that less horrifically inefficient than it sounds, but the visible effects are the same).

So, "1" == 1 is totally fine. You only get a warning when you try to do something like "1x" == 1.

And yes, this is hands-down the most horrifying part of a generally horrifying language.

  • Is there a way to mark $self->room_version as a string so that == 1 throws up warnings?

Sadly no, I'm not aware of anything like type annotations for perl.

You found the main reference. A couple of examples of the differences:

  • "01" == "1", but "01" ne "1" is false
  • "1foo" == "1" (and omits a warning), but "1foo" ne "1"` (when you cast to a numeric value, it just uses the numeric prefix.)

@richvdh
Copy link
Member Author

richvdh commented Feb 22, 2022

In terms of comparing other things, you're really talking about casting those other things to numbers or strings, and then comparing the results. You can also force such a conversion by adding zero ($thing + 0) or the empty string ($thing . "") respectively. You might also see scalar($thing) which is normally equivalent to stringifying it.

So...

  • Arrays numify and stringify to the number of entries in the array (so @a == @b and @a eq @b compare the length of @a and @b). If that was my intention, I would use == since I'm comparing numeric values.
    • If I wanted to compare the contents of the arrays, I'd either write a function or hunt for a package. There are many contenders.
  • Until recently hashes stringified to some weird internal thing, so comparing them was pretty useless. Nowadays you get the number of pairs in the hash. (So again, %a == %b compares the length of %a and %b).
  • references to arrays and hashes numify to the internal address of the referee, so comparing them with == checks that both reference refer to the exact same thing. They also stringify to a unique string based on the internal address of the referee, so comparing them with eq also does that.
    • If I actually had a usecase for checking two references refer to the same thing, I'd probably use refaddr and use ==, which would be more explicit
  • objects are really just fancy hashes, so by default, references to objects do the same as references to hashes. But for added fun, objects can overload the numification or stringification operations, as well as == and eq themselves. So I'd be looking to see if a particular class had defined behaviour here before using either on an object reference.

TL;DR: there are a couple of cases where using eq or == on other things is sensible (comparing array length, comparing objects with defined semantics), but in general it's not wise.

@richvdh
Copy link
Member Author

richvdh commented Feb 22, 2022

(I'm assuming the test failure is a flake here?)

I believe so.

@richvdh richvdh merged commit ac18840 into develop Feb 22, 2022
@richvdh richvdh deleted the rav/stringy_room_ver branch February 22, 2022 11:39
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

Successfully merging this pull request may close these issues.

2 participants