For Development HEAD DRAFTSearch (procedure/syntax/module):

6.5 Undefined values

While working with Gauche, sometimes you encounter a value printed as #<undef>, an undefined value.

gosh> (if #f #t)
#<undef>

It is a value used as a filler where the actual value doesn’t matter, or there’s no other suitable value, or the binding hasn’t been calculated.

Do not confuse undefined values with unbound variables; A variable can be bound to #<undef>, for it is just an ordinary first-class value. On the other hand, an unbound variable means there’s no value associated with the variable.

However, #<undef> may be used in certain occasions to indicate that a value is not provided for the variable. For example, the toplevel variable can be bound to #<undef> if it is defined by (define variable) form (see Definitions). An optional procedure parameter without default value is bound to #<undef> if an actual argument is not given (see Making procedures).

Note that it cannot be distinguished from the case a value is actually provided, and the value just happens to be #<undef>. If you get an #<undef>, you can say at most is that the value doesn’t matter. You shouldn’t let it carry too much meanings.

The #<undef> value is counted as true value in generalized boolean context, since it is not #f. However, branching based on #<undef> is dangerous—a procedure that is defined to return unspecified value may merely returning #<undef> as a provisional value; it will change the return value in future. Since the return value isn’t specified, no one should be using it. The code that tests such result value as a generalized boolean may break if the procedure changes the return value.

In fact, we’ve found that there are quite a few code that accidentally tests #<undef> return value in conditionals. They can be seeds for future bugs, so we warn when #<undef> value is used in the test of branches. You can suppress the warning with setting the environment variable GAUCHE_ALLOW_UNDEFINED_TEST.

One typical case of such accidental use of #<undef> branching is in and-let*; the following code assumes display always return #<undef>, which is counted as a true value, and expects the control to proceeed to the next clause. It’ll break if display ever changes so that it may return #f in some cases.

(and-let* ([var (foo x y z)]
           [ (display var) ]    ;; branch on #<undef>
           [baz (bar var)])
  ...)

Being said that, there are a couple of procedures to deal with undefined values.

Function: undefined? obj

Returns #t iff obj is an undefined value.

Function: undefined

Returns an undefined value.



For Development HEAD DRAFTSearch (procedure/syntax/module):
DRAFT