関数に不適切な型の引数が渡されると、Lispインタプリタはエラーメッセージを出力します。例えば、+
関数は引数の値が数値であることを想定しています。試しに、数値の代わりにクォートされたシンボル hello を渡してみましょう。次の式の後にカーソルを置き、C-x
C-e と入力してください:
(+ 2 'hello)
このようにすると、エラーメッセージが表示されます。何が起きたかというと、+ が 'hello から返された値に 2 を加算しようとしましたが、'hello から返された値は数値ではなくシンボル hello だったためです。加算できるのは数値のみです。そのため、+ は加算を実行できませんでした。
次のような内容の *Backtrace* バッファを作成して入力します:
---------- Buffer: *Backtrace* ---------- Debugger entered--Lisp error: (wrong-type-argument number-or-marker-p hello) +(2 hello) eval((+ 2 'hello) nil) elisp--eval-last-sexp(nil) #f(compiled-function () #<bytecode ...>)() handler-bind-1(#f(compiled-function () #<bytecode ...>) (error) eval-expression--debug) eval-last-sexp(nil) funcall-interactively(eval-last-sexp nil) call-interactively(eval-last-sexp nil nil) command-execute(eval-last-sexp) ---------- Buffer: *Backtrace* ----------
いつものことながら、エラーメッセージは親切を装っており、読み方さえ分かれば意味が通じるようになっています。4
エラーメッセージの前半部分は単純で、‘wrong type
argument’と書かれています。次に、謎の専門用語である‘number-or-marker-p’が登場します。この言葉は、+がどのような引数を期待していたのかを伝えようとしています。
記号 number-or-marker-p
は、Lispインタプリタが、与えられた情報(引数の値)が数値なのか、あるいはマーカー(バッファ位置を表す特殊なオブジェクト)なのかを判定しようとしていることを示しています。具体的には、+
に加算するための数値が与えられているかどうかを確認します。また、引数がマーカーと呼ばれるものであるかも確認します。これはEmacs
Lisp特有の機能です。(Emacsでは、バッファ内の位置をマーカーとして記録します。C-@ や C-SPC
コマンドでマークを設定すると、その位置がマーカーとして保持されます。マークは数値――バッファの先頭からその位置までの文字数――とみなすことができます。)Emacs
Lispでは、+ を使用して、マーカー位置の数値を数値として加算することができます。
number-or-marker-p の ‘p’ は、Lispプログラミングの黎明期に始まった手法を具現化したものです。‘p’ は 述語
を意味します。初期のLisp研究者が用いた専門用語において、述語とは、ある性質が真か偽かを判定する関数のことを指します。したがって、‘p’ は、number-or-marker-p
が、与えられた引数が数値であるかマーカーであるかが真か偽かを判定する関数の名前であることを示しています。‘p’ で終わる他のLispシンボルには、引数が0であるかどうかを判定する関数 zerop や、引数がリストであるかどうかを判定する関数 listp などがあります。
最後に、エラーメッセージの最後の部分はシンボル hello です。これは + に渡された引数の値です。もし加算に正しい型のオブジェクトが渡されていたなら、渡された値は hello のようなシンボルではなく、37
のような数値になっていたはずです。しかし、そうなればこのエラーメッセージは表示されなかったでしょう。