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

6.5 未定義値

Gaucheで作業していると、しばしば未定義値 #<undef> に出会うことがあるでしょう。

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

この値は、値そのものに意味が無いこと、 ほかにふさわしい値が無いこと、あるいは束縛する値がまだ計算されていないことを示します。

未定義値と未束縛の変数を混同しないようにしてください。 #<undef>は通常の第一級の値であり、変数に束縛しておくこともできます。 未束縛の変数は文字通り、変数が束縛されていない、すなわち値を持たないことを意味します。

しかし、場合によっては、変数に特定の値が提供されていないことを 示すのに#<undef>が使われることもあります。 例えば、トップレベル変数は、(define variable)の形式で定義された場合に #<undef>に束縛されます(定義参照)。 また、既定値をもたない省略可能引数に実引数が提供されなかった 場合、引数の値は#<undef>となります (手続きを作る参照)。

これは実際に#<undef>が初期値として、あるいは引数として渡された場合と区別がつかない ことに注意してください。#<undef>を受け取ってわかることは、 せいぜいその値にたいした意味がないということくらいです。 #<undef>に大きな意味を持たせすぎないようにしましょう。

#<undef>は一般化された真偽値としては真の値とみなされます (偽になるのは#fのみですから)。 しかし、#<undef>の値を見て分岐するコードは危険です。 というのも、戻り値が規定されていない手続きが暫定的に#<undef>を返している 場合が良くあるからです。でも、それは将来変更されるかもしれません。 戻り値が規定されていない以上、戻り値に依存するコードは無いはずだからです。 もしうっかり、その戻り値に基づいて分岐しているコードがあると、変更があったときに 壊れてしまいます。

実のところ、#<undef>に依存して分岐しているコードが結構多いことがわかりました。 これは将来のバグの芽となるので、#<undef>が分岐テストに現れた場合には 警告が出されます。この警告をオフにするには 環境変数GAUCHE_ALLOW_UNDEFINED_TESTをセットしてください。

#<undef>をうっかり分岐テストに使ってしまう良くあるパターンは、 and-let*です。次のコードでは、displayがテスト節に現れていますが、 このコードはdisplayが常に#<undef>を返しそれが真の値であることから 次のテスト節に進むことを期待しています。けれども、displayが場合によっては#fを 返すように変更されたら、このコードは壊れてしまいます。

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

以上の注意を念頭においた上で、未定義値を扱うには 次の手続きが利用できます。

Function: undefined? obj

objが未定義値である場合に限り#tを返します。

Function: undefined

未定義値を返します。



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