Hi --

On Sun, 8 May 2005, Cyent wrote:

> Nil arises in several places that I can think of.
>
> The most obvious case, and the case I think most people are concerned
> about, is when referencing an uninitialized variable.

That pertains only to instance and global variables, and I don't
remember seeing a lot about it (though I haven't tallied the
responses).

> This case is flagged by -w, and hence I had mentally disregarded the
> possibility when I wrote RCR 303.
>
> The next case is when nil is returned by something like a regex match or
> an index out of bounds.

That seemed to me to be what people were talking about mostly --
things like:

    /som(e n)on-matc(hing) regex/.match("blah").captures

> The third case is when explicit set by the programmer, typically as a
> default parameter to a method.
>
> The fourth case is to get around the lexical scoping umfeature of rubies
> local variables.
>
> def foo
>  my_var = nil
>  box.each do |e|
>    my_var = e if e.blah
>  end
>
>  use_var( my_var)
> end
>
> This is another case of "nil means uninitialized".

It's not that, exactly; rather, you're initializing a variable to nil.
You've chosen nil to represent the initialized state of the variable,
not an uninitialized state.  Once you assign to it, it's initialized.

> So what we have is a "nil" is a little too busy, means too much, is
> overloaded too heavily.

I'm not sure where the "too"s come from.  How do you determine how
much (or little) use should be made of such a construct?  You can
always initialize your variables to something else if you don't like
using nil too much :-)

> It means "uninitialized".
>
> It also means "no thing here" (as in return from regexp match (no
> MatchData here), index out of bounds (no Array element here), and nil as a
> default value.)

It's not exactly "no Array element here"; it's more a default value.
You can have nil as an array element; therefore, it cannot mean that
there's no element.  As with hashes, of course, the retrieval of the
default value does not initialize the element:

    ruby -we 'a = []; a[3]; p a.size'
    0

> I perfectly agree that "uninitialized" should throw a
> NoMethodError.

That's not what happens, though.  If a local variable is
uninitialized, you find out before you get to the point of sending it
a message:

   bash-2.04$ ruby -e 'a.b'
   -e:1: undefined local variable or method `a' for main:Object
   (NameError)

whereas NoMethodError happens when you send a message to an object.

> Indeed I doubt if it should respond to some of the
> methods it does respond to currently. I even think -w is too friendly, I
> would prefer it to throw than to just warn.
>
> What I as thinking of by RCR 303 is nil as "no thing here" should respond
> to all methods, do nothing and return "no thing here".
>
> So perhaps I should retract RCR 303 and created a new one suggesting  and
> differentiation between "uninitialized" and "no thing here", and
> effectively RCR-303 for "no thing here".
>
> I would welcome suggestions as to how to craft this new RCR.

A few years ago there was a discussion of some kind of NACK mechanism
-- meaning, something that an object could give as a reponse when it
didn't recognize a message, instead of raising NoMethodError.  My main
goal was to avoid this:

    obj.meth if obj.respond_to?(:meth)

a repetition I've always disliked, and at the same time to avoid
having to do this:

    begin
      obj.meth
    rescue NoMethodError
      ...
    end

The big problem with NACK, though, was that it was incompatible with
method_missing: it offered a different way to handle the same
situation.  Anyway, I thought the concept might be of interest in
connection with the problem you're working on, and perhaps you can
engineer it successfully.


David

-- 
David A. Black
dblack / wobblini.net