Crystal: Remove the `nil?` method?

Created on 29 Mar 2016  Â·  9Comments  Â·  Source: crystal-lang/crystal

We copied the nil? method from Ruby. People coming from Ruby use it and find out it has unexpected behaviour in Crystal. For example:

x = some_nilable_value
if !x.nil?
  x.foo # Error, x might be nil
end

The problem is that nil? doesn't do what we call "type filtering": the compiler doesn't know x won't be nil inside the if. An alternative to the above is this:

x = some_nilable_value
if x
  x.foo # OK
end

The above works and is semantically equivalent as long as x's type doesn't include Bool. In that case, one can do:

 x = some_nilable_value
unless x.is_a?(Nil)
  x.foo # OK
end

(or if !x.is_a?(Nil) once and if we implement #1196)

Alternatively, we can make the compiler have .nil? as equivalent to .is_a?(Nil) and disallow defining this method, but, as always, I'd like to keep the language simple.

What do you think?

Most helpful comment

I would prefer to keep the .nil? and I see a bonus to translate it to .is_a?(Nil) in order to gain the type filtering. Nil is special after all.

I actually prefer to be explicit in if regarding not nil check. If I don't use .is_a?(Nil) is because it's too verbose compared to .nil?.

But I know in my head this goes all way back to avoiding anything but booleans in conditions. But still, I like to be able to be explicit regarding .nil?

All 9 comments

+1 on removing it. I use if x, or if x = method_call(...) form. Haven't
used #nil? so far.

Best Regards,
Oleksii Fedorov,
Programmer,
Software Craftsman (http://manifesto.softwarecraftsmanship.org/),
TDD, Pair-Programming, Microservices, Good Architecture, Ruby, Clojure, Go,
a bit of Web Frontend and more,
Follower of Software Engineering Code of Ethics (
http://www.acm.org/about/se-code),
+49 15757 486 476

On Tue, Mar 29, 2016 at 7:05 PM, Ary Borenszweig [email protected]
wrote:

We copied the nil? method from Ruby. People coming from Ruby use it and
find out it has unexpected behaviour in Crystal. For example:

x = some_nilable_valueif !x.nil?
x.foo # Error, x might be nilend

The problem is that nil? doesn't do what we call "type filtering": the
compiler doesn't know x won't be nil inside the if. An alternative to the
above is this:

x = some_nilable_valueif x
x.foo # OKend

The above works and is semantically equivalent as long as x's type
doesn't include Bool. In that case, one can do:

x = some_nilable_valueunless x.is_a?(Nil)
x.foo # OKend

(or if !x.is_a?(Nil) once and if we implement #1196
https://github.com/crystal-lang/crystal/issues/1196)

Alternatively, we can make the compiler have .nil? as equivalent to
.is_a?(Nil) and disallow defining this method, but, as always, I'd like
to keep the language simple.

What do you think?

—
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub
https://github.com/crystal-lang/crystal/issues/2387

I would prefer to keep the .nil? and I see a bonus to translate it to .is_a?(Nil) in order to gain the type filtering. Nil is special after all.

I actually prefer to be explicit in if regarding not nil check. If I don't use .is_a?(Nil) is because it's too verbose compared to .nil?.

But I know in my head this goes all way back to avoiding anything but booleans in conditions. But still, I like to be able to be explicit regarding .nil?

@bcardiff The point about nil being special is true, so maybe having nil? as a short form of is_a?(Nil) is good. After all the compiler knows about nil, for example in if and while, and the standard library has not_nil! and so on. And people coming from Ruby won't be surprised... though their code might result being a bit more verbose than current Crystal code (just doing if x).

+1 for nil? => is_a?(Nil)

Sometimes, _slight_, verbosity is good to clarify intent :-)

I feel like testing for x being true vs nil? are not exactly equivalent.
This is where rspec gets its truthy vs falsey semantics which are very useful. I found this writeup, which was helpful in understanding the utility. https://gist.github.com/jfarmer/2647362

Based on the comments above and some discussions we had with @waj and @bcardiff we decided that the best thing to do is to make nil? be the same as is_a?(Nil). The reasons are:

  1. Nil is already "special": the compiler knows about it and many language constructs (if, while, &&) do type filtering around it. It makes sense to make nil? have a similar behaviour.
  2. nil? is used a lot by Ruby programmers. It's better if nil? works and does type filtering as one would expect.
  3. if x.nil? and unless x have a different meaning. The later passes if x is false, so it makes sense to have a (short) way to check for nil-ness (is_a?(Nil) is much longer and involves parentheses).
  4. It's really simple to implement, just syntax sugar :-)

I noticed there was Pointer#nil? which meant "returns true if the pointer's address is zero". I removed that method because it was misleading. Even though a null pointer is falsey, it's not nil (it's type is not Nil). So if you used Pointer#nil? you have to use now Pointer#null?. The bad thing is that it's not easy to spot where Pointer#nil? is used, so you'll have to go one by one and replace them... but this should only affect shards that deal with pointers (most probably C bindings). I prefer to break this now and have nil? be consistent with its meaning. (I'll write a big note about this in the next release notes/changelog)

I forgot to say, in the next release I'll also make the compiler give an error if you try to define a method named nil?, is_a?, responds_to? or !. I can't do that right now because nil? is still defined in the current compiler.

Should the to_s of and ASTNode or the formatter prefer to use .nil? syntax over .is_a?(Nil) ?

@bcardiff We could probably make is_a?(Nil) and nil? appear as nil?. In any case if we don't have two different nodes for nil? and is_a?(Nil) the to_s representation will have to always be one of those. And they both work in the same way, so I think it doesn't matter much how we show it.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

Papierkorb picture Papierkorb  Â·  3Comments

nabeelomer picture nabeelomer  Â·  3Comments

grosser picture grosser  Â·  3Comments

lbguilherme picture lbguilherme  Â·  3Comments

pbrusco picture pbrusco  Â·  3Comments