I try to compare flags in my Ruby application.
I have this code :
if self.flag &~ flag == self.flag
return false
But it won't run. I've narrowed the problem to this :
irb(main):020:0> my_user.flag
=> 1
irb(main):021:0> flag
=> 128
irb(main):022:0> my_user.flag.class
=> Fixnum
irb(main):023:0> flag.class
=> Fixnum
irb(main):024:0> my_user.flag &~ flag
TypeError: wrong argument type Fixnum (expected Proc)
That is really disturbing since it works like this :
irb(main):025:0> 1 &~ 128
=> 1
The difference between
1 &~ 128andmy_user.flag &~ flagis that the second expression involves a dot-method call. That changes the way the subsequent tokens are interpreted.Try this:
You'll find that it works. This is because adding
()or moving~changes the order of operations to be more in line with what you expected.The original method call you're using is actually interpreted by Ruby as:
This order of operations first flips the bits in
flagby applying the~operator, then attempts to callto_procon the resultingFixnumbecause of the application of the&(cast-as-block) operator, and then finally attempts (had that not thrown aTypeError) to pass it as a block argument to theUser#flagmethod.