Displaying posts written in

7月 2009

SUBST-IFの動作に注意

『実践Common Lisp』13.1のSUBST-IFについての説明は間違っている。

SUBST-IFは、古いアイテムを1つ受け取る代わりに、1引数関数を受け取る。この関数は木に含まれる各アトミックな値に対して呼び出され、その結果が真になった箇所をすべて新しい値で置き換えた新しい木を返す。

「各アトミックな値に対して呼び出され」とあるが、実際にはコンスセルも含む(木自体も含む)全ての要素に対して呼び出される。SUBST-IF-NOTなども同様。

(subst-if 10 #'consp '(1 3 2 (1 2) (3 4) (5 6)))
;; => 10
 
(subst-if 10 #'atom '(1 3 2 (1 2) (3 4) (5 6)))
;; => (10 10 10 (10 10 . 10) (10 10 . 10) (10 10 . 10) . 10)
 
(subst-if 10 #'evenp '(1 3 2 (1 2) (3 4) (5 6)))
;; => エラー
;; The value (1 3 2 (1 2) (3 4) (5 6)) is not of type INTEGER.
 
(subst-if 10 #'(lambda (x) (and (integerp x) (evenp x)))
	  '(1 3 2 (1 2) (3 4) (5 6)))
;; => (1 3 10 (1 10) (3 10) (5 10))

そもそもアトミックな値も定義上は木である。

(subst-if 10 #'evenp 2)
;; => 10