(1..5) === 3 > true 3 === (1..5) > false

M

Michael Chow

(1..5) === 3 > true
3 === (1..5) > false

Is this a bug or expected behavior? From my understanding it shouldn't
matter on which side of an equal comparison an expression appears.
 
T

Todd Benson

(1..5) === 3 > true
3 === (1..5) > false

Is this a bug or expected behavior? From my understanding it shouldn't
matter on which side of an equal comparison an expression appears.

It's one of those "you have to read the docs" things. The === method
for Range is left-sided because it's a method. You can redefine it if
you want.

class Range
def ===(o)
puts o
end
end

(1..5) === 3
# 3
# => nil
 
M

Michael Chow

I know it's a method, but why doesn't Fixnum's === work properly with
ranges?

That should be the expected behavior, the expression is just as true one
way as it is the other.
 
P

Phrogz

I know it's a method, but why doesn't Fixnum's === work properly with
ranges?

That should be the expected behavior, the expression is just as true one
way as it is the other.

What do you think "===" means? Hint: it's not the same as "==", or
"<<". And it doesn't mean "is equals to". Obviously (1..5) does not
equal 3.

The #=== method is called in case statements, and it is up to each
class to define something reasonable.

case 3
when 1..5
puts "(1..5) === 3 means 3 is inside the range."
when Integer
puts "Integer === 3 means that 3 is a sort of Integer"
end
 
J

Joel VanderWerf

Michael said:
(1..5) === 3 > true
3 === (1..5) > false

Is this a bug or expected behavior? From my understanding it shouldn't
matter on which side of an equal comparison an expression appears.

It's normal for the #=== operator to be asymmetric, even though it looks
symmetric. The LHS is treated as a _pattern_ for matching the RHS.

For example:

String === "foo"

uses different criteria than

"foo" === String

and likewise for

/fo/ === "foo"

vs

"foo" === /fo/

Also, note that #=== is used in case statements.

case 3
when 1..5
...
end

works as you expect, because it is equivalent to

if (1..5) === 3
...
end

But this wouldn't make sense:

case 1..5
when 3
...
end

so it really needs to be asymmetric.
 
A

Alex Young

Phrogz said:
What do you think "===" means? Hint: it's not the same as "==", or
"<<". And it doesn't mean "is equals to". Obviously (1..5) does not
equal 3.

The #=== method is called in case statements, and it is up to each
class to define something reasonable.

case 3
when 1..5
puts "(1..5) === 3 means 3 is inside the range."
when Integer
puts "Integer === 3 means that 3 is a sort of Integer"
end

Mentally, I parse "===" as "contains". That requires a little mental
judo for RegExps, but that's a good thing :)
 
G

Giles Bowkett

I know it's a method, but why doesn't Fixnum's === work properly with
ranges?

That should be the expected behavior, the expression is just as true one
way as it is the other.

I'm reading this as incredibly whiny, childish, and obnoxious, but
that could be totally my own perception.

The whole point of Ruby is that if you don't want things to happen the
way they happen, you can rewrite large portions of the language -
including this piece - with very little effort. So not only is it
pointless to tell people what the language should do, but also, if you
really want the language to do that, you can **make** it do that with
hardly any effort at all.

Anyway. The reason threequals doesn't behave the way you expect it to
is because you don't know what it's for. It's not something you should
use in day-to-day code. It's not an equality operator. That's why it
doesn't have the associative property which equality has. Threequals
is for defining how a class should be evaluated in a case/when
statement. Unless you're defining how a class should be evaluated in a
case/when, you shouldn't be using threequals.

So threequals is in fact working properly. You just don't know how to
use it. The way to use it is to define a new class and then use
threequals to define how a case/when will evaluate that class. Many,
many people will never ever need to do this, because it's a relatively
esoteric use case.

More detail, and less grumpiness:

http://gilesbowkett.blogspot.com/2007/11/what-is-threequals.html

--
Giles Bowkett

Podcast: http://hollywoodgrit.blogspot.com
Blog: http://gilesbowkett.blogspot.com
Portfolio: http://www.gilesgoatboy.org
Tumblelog: http://giles.tumblr.com
 
F

Francis Burton

Giles said:
The whole point of Ruby is that if you don't want things to happen the
way they happen, you can rewrite large portions of the language -
including this piece - with very little effort. So not only is it
pointless to tell people what the language should do, but also, if you
really want the language to do that, you can **make** it do that with
hardly any effort at all.

Is there a construct like this in Ruby?

if x in (1..5)

This seems a lot more intuitive and easier to read than "(1..5) === x",
so is it possible to modify the language to make it do that?

Francis
(Ruby nuby)
 
M

Marcin Mielżyński

Francis Burton pisze:
Is there a construct like this in Ruby?

if x in (1..5)

This seems a lot more intuitive and easier to read than "(1..5) === x",
so is it possible to modify the language to make it do that?

Francis
(Ruby nuby)

Use (1..5).include? x. Ruby tends to use methods instead of abusing
keywords.

lopex
 
S

Sebastian Hungerecker

Francis said:
Is there a construct like this in Ruby?

if x in (1..5)

This seems a lot more intuitive and easier to read than "(1..5) === x",
so is it possible to modify the language to make it do that?

First of all: You usually wouldn't use ===, you'd use (1..5).include? x
which is more readable in that it tells the reader what it does (=== is
really only used for things like case and grep - you rarely (if ever) use
it explicitly).
To answer your question: Yes, it is:
class Object
def in?(collection)
collection.include? self
end
end

if x.in? 1..5
...
end

For numbers there's also x.between?(1,5)


HTH,
Sebastian
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,289
Messages
2,571,435
Members
48,120
Latest member
Natbelix

Latest Threads

Top