by shigemk2

当面は技術的なことしか書かない

リスト遊び 7-4 catch と throw

前回
リスト遊び 7-3 数え上げ - by shigemk2

制御の流れを強制的に変える特殊関数。

(catch シンボル
  ...
  (throw シンボル 式)
  ...
  )

throwはcatchの内側に置き、第一引数がcatchに指定したシンボル、
第二引数がcatchの返す値となる。
catchの本体が上から順に評価していく過程で、throwが評価された
場合は、対応するラベルの持つcatchの本体から抜け出し、throwの第二引数が
catchの返す値となる。throwが評価されない場合は、catchの本体で最後に評
価された値が返される。


catch throwの一般的な使いかたは、whileによる繰り返しを途中で
強制的に終了すること。catchでループに名前をつけ、ある条件が満たされた
ときにthrowでその繰り返しを強制終了する。

(defun memq (x set)
  (catch 'loop ;; loop=tのとき、throwが発動し、ループを終了させる
    (while set
      (cond
       ((eq x (car set))
	(throw 'loop t)))
      (setq set (cdr set)))))
memq
(memq 5 '(1 5))
t
(memq 5 '(5 1 1 5))
t
(memq 5 '(1 1 1 3))
nil

assq2

(defun assq (key alist)
  (let (a)
    (catch 'loop
      (while alist
	(setq a (car alist))
	(setq alist (cdr alist))
	(cond
	 ((eq key (car a))
	  (throw 'loop a)))))))
assq
(assq 1 '((2 . 1)))
nil
(assq 1 '((1 . 1)))
(1 . 1)

car がいっぱい出てきてカオスなので、alistのcarはaとした。

リスト遊び―Emacsで学ぶLispの世界 (ASCII SOFTWARE SCIENCE Language)

リスト遊び―Emacsで学ぶLispの世界 (ASCII SOFTWARE SCIENCE Language)