views:

116

answers:

5

How does Ruby's nil manifest in code? For example, in Python you might use None for a default argument when it refers to another argument, but in Ruby you can refer to other arguments in the arg list (see this question). In JS, undefined pops up even more because you can't specify default arguments at all. Can you give an example of how RubyNone pops up and how it's dealt with?

I'm not looking for just an example using nil. Preferably it would be a real code snippet which had to use nil for some reason or other.

A: 

My Ruby-fu is very weak, but nil might be what you are looking for. Here is a quick illustration of using nil in a function as default argument.

irb(main):003:0> def foo(a = nil)
irb(main):004:1> puts a
irb(main):005:1> end
=> nil
irb(main):006:0> foo(1)
1
=> nil
irb(main):007:0> foo()
nil
=> nil
irb(main):008:0> 
Manoj Govindan
Don't get confused by the `=> nil` in the output up there: that's irb showing the the return value of the `foo` method.
glenn jackman
+3  A: 

Ruby's nil and Python's None are pretty much equivalent, but people coming from Python may find surprising things like these:

Arrays and indexes:

array = [1,2,3]
array[999] # nil

Hashes and keys:

hash = {"a" => 1, "b" => 2}
hash["nonexistent"] # nil

Instance variables:

class MyClass
  def initialize
    puts @thisdoesnotexist # prints nil
  end
end
mc = MyClass.new

nil is an object with lots of methods. You can even convert it to integer, float or string!

nil.to_i # 0
nil.to_f # 0.0
nil.to_s # ""

Unsurprisingly, some Python programmers tend to dislike this promiscuous behaviour, but it's ok once you are used to it.

I am not sure this answers your question, just my 2 cents.

tokland
what does the `@` mean in the instance variable example?
Claudiu
Instance variable names start with `@`, class variables with `@@`.
Michael Kohl
@x is equivalent to self.x in Python (though the OOP patterns in Ruby and Python are very different).
tokland
+2  A: 

One use of nil you often see in Ruby code is the following:

a ||= 10 # or a = a || 10

This works because once a variable has been seen on the left hand side of an assignment, it implicitly has the value nil.

>> if false 
..   x = y
..   z
..   end
=> nil
>> x
=> nil
>> z
NameError: undefined local variable or method `z' for main:Object

Thus when the a || 10 part is evaluated, it evaluates to nil || 10, which yields 10.

nil and false are also the only two values in Ruby that are logically false, so it's customary for methods to return nil in case of failure. There's a gem called andand that makes use of exactly this, so instead of something like

@first_name &&= @first_name.trim

you can write

@first_name.andand.trim

This basically translates to trim @first_name if it has a value other than nil, otherwise evaluate to nil. As you can imagine this is particularly useful when chaining methods where one of the intermediaries can potentially return nil.

Besides that nil is also returned when you are trying to access non-existing collection elements, e.g. in the case of arrays or hashes. Uninitialized instance variables also have the value nil.

I'm not overly versed in Python, but from what I've seen nil and None serve pretty much the same purpose.

Michael Kohl
now that "andand" pops up, I have to recommend the ick project (same author) and it's "maybe" pattern, really nice! this_may_be_nil_or_a_string.maybe.strip # string stripped or nil
tokland
`andand` and `maybe` remind me of the `Maybe` monad in Haskell.
Claudiu
Very nice, forgot about `ick`, thanks for adding it :-)
Michael Kohl
@Claudiu: Not to be confused with the `mebbe` keyword in lolcode.
Andrew Grimm
A: 

They’re also used in place of void: In a static language the compiler will simply forbid you from using the return value of a void function, but in a dynamic language every procedure has to return something. So the special value nil is used.

jleedev
it's possible to have a dynamic language which would just throw an exception if you try to use the result of a function that didn't return anything. i just dont think any do it.
Claudiu
A: 

In addition to all explanations about nil, ruby also has 'defined?'.

a = nil

p defined?(a)  #=> "local-variable"
p a.nil?       #=> true
p defined?(b)  #=> nil
steenslag