Live data from Hacker News

Don't overload #nil? in Ruby

paul.rosania.org

11–20 of 40 posts

Re: Don't overload #nil? in Ruby

#11

Conceptually, nil != false. You shouldn't use 'nil' to mean 'false'. You should always test explicitly for nil-ness using #nil?. If you write if finished? do_something end then finished? is not expected, and may not, return nil. If you expect some_value to be able to be nil (which, for boolean values, is hardly ever), you should write if !some_value.nil? && some_value do_something end In the end, these 'convenient' c…

By the same argument, nil != true.

This could lead to a tri-state ifs (with true/false/nil branches).

Or you can just consider that 2-branch 'if' runs the first branch if the test expr is true and the second 'otherwise'. (So that doesn't make nil false, it just makes it non-true).

And then your interpretation and everyone else co-exists and we can all code together.

Re: Don't overload #nil? in Ruby

#12
post #3

Earlier quoted context omitted.

Such code is everywhere in the Ruby community and explicitly endorsed by many. I have never seen code like your second example in the wild, and it's far more complicated than the idiomatic way of writing it: if some_value do_something end It's a core expectation of the language that !!nil_thing == false, so why violate it?

Because when you write if !some_value do_something end you often don't actually want it to be executed when some_value is nil instead of false. And when it is, you go scratching your head and searching where some_value came from, to discover some silly typo. In some ways, the reverse is even worse: when you write if some_value do_something end and you change some_value from nil to some sensible default like '', you w…

I agree with aphyr's response to you. This has never been a problem for me. I think your issue is that you consider an empty string to be a sensible default representing false or nil.

Re: Don't overload #nil? in Ruby

#13
post #12

Earlier quoted context omitted.

Because when you write if !some_value do_something end you often don't actually want it to be executed when some_value is nil instead of false. And when it is, you go scratching your head and searching where some_value came from, to discover some silly typo. In some ways, the reverse is even worse: when you write if some_value do_something end and you change some_value from nil to some sensible default like '', you w…

I agree with aphyr's response to you. This has never been a problem for me. I think your issue is that you consider an empty string to be a sensible default representing false or nil.

I fully agree that those sane defaults indeed aren't right for representing false or nil. What I'm arguing is rather the reverse: nil is often initially used as an (insane?) default and that is later changed without updating all related checks (because they don't stick out and demand attention, which makes them easy to overlook or 'overthink'), which causes bugs.

Re: Don't overload #nil? in Ruby

#14
Isn't this a flaw in Ruby, though? It also means that you can't create a delegate/decorator/proxy object for a false object and have it be false as well, which goes against the general "everything is determined by sending messages" vibe Ruby has going on.

I know the reasoning (it's much faster to do math on object IDs than it is to call a method), but there are workarounds for this (e.g. only allowing frozen objects to be boolean-false, and having the object's truth-ness/false-ness represented by the return value of its #false? method at the time of freezing—thus allowing the interpreter to locate it in a semantically-meaningful part of object-ID space that can later be masked for in a TEST instruction.)

Re: Don't overload #nil? in Ruby

#15
I've said this in a comment at rosania.org, but I think it bears repeating here: this is why we need a #blank? or #null? protocol that user classes can participate in as part of core. #nil? and an inextensible FalseClass just aren't enough to do the sorts of thing that Avdi was trying to do in his original post. My tentative proposal is languishing here: http://redmine.ruby-lang.org/issues/5372

Re: Don't overload #nil? in Ruby

#17
I'm not sure I like it, but this works

    def nil.method_missing(*args, &block); end
So now you can call nil.whatever.you.like and get nil. It's also still falsy, but now every nil value in your app silently works and doesn't throw an error.

It's both impressive and scary that Ruby lets you (or that new contractor you're not sure about) change the fundamentals of the language in one line of code.

Re: Don't overload #nil? in Ruby

#18
post #14

Isn't this a flaw in Ruby, though? It also means that you can't create a delegate/decorator/proxy object for a false object and have it be false as well, which goes against the general "everything is determined by sending messages" vibe Ruby has going on. I know the reasoning (it's much faster to do math on object IDs than it is to call a method), but there are workarounds for this (e.g. only allowing frozen objects…

With infinite spare time, what I'd try would be to make NilClass usable as a base class. The way that would work would be to have all instances of classes inheriting from NilClass live in the 0bXXX...XXX100 object ID space. Nil is currently 0b100, which is consistent, and this doesn't clash with any of the other immediates - it just translates to a different memory alignment rule in MRI.

Re: Don't overload #nil? in Ruby

#19

I'm not sure I like it, but this works def nil.method_missing(*args, &block); end So now you can call nil.whatever.you.like and get nil. It's also still falsy, but now every nil value in your app silently works and doesn't throw an error. It's both impressive and scary that Ruby lets you (or that new contractor you're not sure about) change the fundamentals of the language in one line of code.

Some consequences:

https://github.com/raganwald/homoiconic/blob/master/2009-02-...

Re: Don't overload #nil? in Ruby

#20
post #3

Conceptually, nil != false. You shouldn't use 'nil' to mean 'false'. You should always test explicitly for nil-ness using #nil?. If you write if finished? do_something end then finished? is not expected, and may not, return nil. If you expect some_value to be able to be nil (which, for boolean values, is hardly ever), you should write if !some_value.nil? && some_value do_something end In the end, these 'convenient' c…

Such code is everywhere in the Ruby community and explicitly endorsed by many. I have never seen code like your second example in the wild, and it's far more complicated than the idiomatic way of writing it: if some_value do_something end It's a core expectation of the language that !!nil_thing == false, so why violate it?

I actually agree with Confusion. All these implicit coercions _will_ bite you. Don't understand why his post is downvoted.
Post reply on HN