Relational operators redux (returning RHS)


(Austin Ziegler) #1

I have only recently started looking over the Ruby language, being
interested in it for a while, but not having enough information to
play with it very well until I picked up the pickaxe book (thanks,
guys!). As I’ve been looking around, though, I came to Hugh Sasse’s
page on relational operators in Ruby[1], originally mentioned in
[ruby-talk:6561]. In this page, he mentions specifically that Dave
Thomas brought up the following objection:

Dave Thomas in [ruby-talk:6562]:

Would ‘==’ produce it’s RHS on success? If so,

x == nil

would always be false.

I’m planning to keep my eyes open as I code to see how often this
would be useful for me.

Nice proposal.

In [ruby-talk:6572], Hugh says he’d probably exclude == and !=.

I don’t honestly know the state of this proposal (there’s no mention
of it in the Pickaxe book, which may or may not mean anything), but
I think it would be a very good thing, and disagree that == and !=
should be excluded.

I’ve spent many hours in the last several years working in Oracle
and other SQL databases, where the special value NULL has to be
handled with care, because the only thing which is true about NULL
is that it doesn’t equal anything, even NULL. (This might be said
that NULL != NULL, but a quick test against another SQL database
says that this relational test returns false as well.) The only
valid test available for NULL is “IS [NOT] NULL”.

I think that this is a Good Thing, personally, and wouldn’t mind
seeing it so in Ruby. I think it would actually match the PoLS, even
though it is a change in existing behaviour. The way I see it, nil
is a special value. Even though nil is represented with a singleton
object, nil for an Object is not necessarily the same as nil for an
Array in a logical sense.

I know I’m bringing up stuff that might be close to two years old,
but I haven’t seen any further discussion on this, and I thought
that it might be worth mentioning about how other systems implement
the handling of NULL/nil values.

-austin
[1] http://www.eng.cse.dmu.ac.uk/~hgs/ruby/comparisons.html

– Austin Ziegler, austin@halostatue.ca on 2002.06.13 at 09.54.27


(Martin S. Weber) #2

Imagine == and != returned rhs:

t == nil ?
nil == t ?
t != nil ?
nil != t ?

enjoy :slight_smile:

-Martin

···

On Thu, Jun 13, 2002 at 11:13:03PM +0900, Austin Ziegler wrote:

[…]
In [ruby-talk:6572], Hugh says he’d probably exclude == and !=.

I don’t honestly know the state of this proposal (there’s no mention
of it in the Pickaxe book, which may or may not mean anything), but
I think it would be a very good thing, and disagree that == and !=
should be excluded.


(HAL 9000) #3

[much interesting snippage]

The way I see it, nil
is a special value. Even though nil is represented with a singleton
object, nil for an Object is not necessarily the same as nil for an
Array in a logical sense.

I know I’m bringing up stuff that might be close to two years old,
but I haven’t seen any further discussion on this, and I thought
that it might be worth mentioning about how other systems implement
the handling of NULL/nil values.

Hmm… in Ruby, nil is a “real” value. It can be compared
to itself or anything else in a meaningful way.

I’d fear changing this. I don’t think I want more than
one kind of nil (if I understand you rightly).

Some languages have many kinds of “false” value. Ruby
has only false and nil. I think that’s one of the
beauties of Ruby.

JM2CW,

Hal Fulton

···

----- Original Message -----
From: “Austin Ziegler” austin@halostatue.ca
To: “ruby-talk ML” ruby-talk@ruby-lang.org
Sent: Thursday, June 13, 2002 9:13 AM
Subject: Relational operators redux (returning RHS)


(Austin Ziegler) #4

True enough. I’m not sure that simple RHS return would be good in
the event that one of the values is nil; but I think that the idea
is fundamentally sound (warning; the following is untested
air-code).

alias :oeq, :==

def == (other)
if other.nil?
false
elsif oeq(other)
other
else
false
end
end

It would be necessary to replace NilClass#== with

class NilClass
def ==(other)
false
end
end

to handle nil on the LHS.

If we have the NilClass replacement and the first code in Fixnum,
then:

x = 5
y = 6

p x == x #=> 5
p x == y #=> false
p x == nil #=> false
p nil == x #=> false

Unfortunately, because != is simply syntactic sugar for ! (x == x),
the != tests aren’t as clean:

p x != x #=> false
p x != y #=> true
p x != nil #=> true
p nil != x #=> true

This means that if this were to become normative behaviour, x != y
would produce surprising results. I’m not quite sure what the proper
answer to this is, but it’s just a thought or two.

As I said, I like the idea that nil isn’t equal to anything,
including nil.

-austin
– Austin Ziegler, austin@halostatue.ca on 2002.06.13 at 10.41.47

···

On Thu, 13 Jun 2002 23:26:52 +0900, Martin Weber wrote:

On Thu, Jun 13, 2002 at 11:13:03PM +0900, Austin Ziegler wrote:

[…]
In [ruby-talk:6572], Hugh says he’d probably exclude == and !=.

I don’t honestly know the state of this proposal (there’s no
mention of it in the Pickaxe book, which may or may not mean
anything), but I think it would be a very good thing, and
disagree that == and != should be excluded.
Imagine == and != returned rhs:

t == nil ?
nil == t ?
t != nil ?
nil != t ?


(Christoph) #5

“Austin Ziegler” austin@halostatue.ca wrote in

is fundamentally sound (warning; the following is untested
air-code).

Still way above my standard;-)

alias :oeq, :==

def == (other)
if other.nil?
false
elsif oeq(other)
other
else
false
end
end

This would also imply false == false # => false

It would be necessary to replace NilClass#== with

class NilClass
def ==(other)
false
end
end

to handle nil on the LHS.

If we have the NilClass replacement and the first code in Fixnum,
then:

x = 5
y = 6

p x == x #=> 5
p x == y #=> false
p x == nil #=> false
p nil == x #=> false

Unfortunately, because != is simply syntactic sugar for ! (x == x),
the != tests aren’t as clean:

p x != x #=> false
p x != y #=> true
p x != nil #=> true
p nil != x #=> true

This means that if this were to become normative behaviour, x != y
would produce surprising results. I’m not quite sure what the proper
answer to this is, but it’s just a thought or two.

As I said, I like the idea that nil isn’t equal to anything,
including nil.

I don’t like this idea, and I am not so sure if the C-heritage of

nan = 0.0 / 0.0
nan.equal? nan # => true but
nan == nan # => false

is really such a good idea.

/Christoph


(Austin Ziegler) #6

“Austin Ziegler” austin@halostatue.ca wrote in

is fundamentally sound (warning; the following is untested
air-code).
Still way above my standard;-)

Heh. Actually, it was tested, and I just forgot to remove that out.

alias :oeq, :==

def == (other)
if other.nil?
false
elsif oeq(other)
other
else
false
end
end
This would also imply false == false # => false

Just as we’d have to do with NilClass#==, FalseClass#== would be
necessary:

class FalseClass
def ==(other)
if other.kind_of?(FalseClass)
true
else
false
end
end
end

Or something like that. It’s not pretty, but I think that there’s
few edge cases around this particular concept which would have to be
dealt with, and NilClass#== and FalseClass#== should take care of
most of them. I think. (The fact that most classes seem to get their
#== from Comparable helps.)

As I said, I like the idea that nil isn’t equal to anything,
including nil.

I don’t like this idea, and I am not so sure if the C-heritage of

nan = 0.0 / 0.0
nan.equal? nan # => true but
nan == nan # => false

is really such a good idea.

I don’t see why it’s a bad idea. It does present a few surprises to
people who aren’t used to a language distinguishing between 0 and
NULL, but it’s intimately familiar to people who do anything with
SQL databases. Literally, when I set colval = NULL in a database, I
am setting it to an ‘unset’ value, which means that I can’t possibly
trust anything about that value except the fact that it’s unset.

It’s rather like doing the following in C (dangerous and stupid):

int *p, *c;

if (*p == *c)
    puts("Miracle!");

We haven’t initialised the pointers p & c, so we’re picking up
whatever values are there. The likelihood of these values actually
matching is minimal. In C, NULL is simply 0, which represents its
own danger. I think that Ruby has a great step toward what I
consider Very Good NULL value handling (the more explicitly you
handle unset values, the better, as far as I’m concerned), but I
think that this would actually make it even better (that is, more
explicit).

If something isn’t a “real” value – much like NaN isn’t a real
value but a concept, the same with nil, why should testing that
imaginary value against itself result in equality? By definition,
these ‘values’ aren’t actually values, but concepts.

Just my .02 Canadian,
-a
– Austin Ziegler, austin@halostatue.ca on 2002.06.13 at 14.22.12

···

On Fri, 14 Jun 2002 02:05:07 +0900, Christoph wrote: