I am puzzled as to why dynamically-typed or type-free languages need a "nil". A dynamic language can use empty strings or "(nil)" or all kinds of stuff to represent nils and nulls from outside systems such as databases. It just adds problems such as 3-value logic expressions. I believe in the PowerOfPlainText, and unprintable stuff is a violation of that, making debugging harder, etc.
Investigate nil-handling in RubyLanguage here. if 0 is the same as if true. if nil is the same as if false. Member variables not seen yet are default-nil. This allows absurdly brief and clear statements. For example, you can say @member ||= slow_operation() to assign the member once, just-in-time before using it. || doesn't evaluate its right argument if the left is true or not-nil, and then ||= assigns as a shortcut.
RubyLanguage needs nil, and does it right
The problem is that there is frequently a different meaning of empty vs nil. Empty means an empty value was given, whereas nil means no value has been given yet. You might be able to convince me that using an empty string could be ok, but using any other string constant such as "(nil)" can have demonstrably bad side effects and should be avoided.
I like the Ruby approach. It has nils, but nils are references to TheNilObject, not references to no object at all. Since nil has methods, including to_s, to_i, etc., it avoids many of the 3-value logic issues. For instance, i.to_s.empty? will return true for either a nill or a zero-length string.
I don't see how such is specific to Rails. It is just a default value to return if the DB gives a null, no? Or is it a Boolean flag that tells you if the DB returned a null? This is typical of a DataDictionary or record management framework.
PerlLanguage also has the "undef" value, which is basically the same as Nil. A common use is to create a subroutine that returns undef in case of a (minor) problem, but the empty string is a valid return. E.g., looking up a value in a database where it is possible to have an empty field. The subroutine would return undef if the key didn't exist, but could return an empty string.
You could argue that exceptions are a better way, but PerlLanguage only has eval/die, which is not a very good substitute for exceptions, either.
I have to admit that I really prefer the approach taken by functional languages here. E.g., there is no singular nil value, but rather, type-safe nils are used. For example:
data MyList? a = EmtpyList? | MyCons? a (MyList? a)Notice that EmptyList? is the "nil" for the type that is MyList? a. By doing this, however, you end up in a situation where there are no true nil values; EmptyList?, though interpreted as if it were a nil value, is really a constructor for a fixed, singleton object (since it takes no parameters, the compiler is free to optimize it to a singleton instance to save memory). Under the hood, pointers to a MyList? instance of some kind would never have a null pointer.
If you need to distinguish conveniently between an empty list from the lack of any list at all, this concept is easily extended:
data MyList? a = NoList? | EmtpyList? | MyCons? a (MyList? a)However, this allows you to cons together a datum with a NoList?. This is a better solution (using Haskell's Maybe type here):
data Maybe a = Nothing | Just a -- already defined in Haskell's Prelude, but included here for completeness data MyList? a = EmptyList? | MyCons? a (MyList? a) type OptionalList? a = Maybe (MyList? a)--SamuelFalvo?
Seconded! Actually, under-the-hood, pointers to 'MyList' can point to memory-address-zero. It need only semantically be the 'EmptyList'.