状態を持った手続きを作る - lisp-cookbook-ja/common-lisp GitHub Wiki
状態を持った手続きを作る
関数にレキシカルな環境を閉じ込むことで状態を持った手続きを作ることができます。
下記の例では、GoFデザインパターンのIteratorパターンをクロージャで真似ています。
(defun make-iterator (sequence)
(let ((idx 0)
(len (length sequence)))
(values (lambda () (setq idx 0))
(lambda () (incf idx))
(lambda () (elt sequence idx))
(lambda () (<= len idx)))))
(multiple-value-bind (first! next! current-item done?)
(make-iterator '(1 2 3 4))
(do ()
((funcall done?))
(print (funcall current-item))
(funcall next!))
(print "Reset!")
(funcall first!)
(print (funcall current-item)))
;-> 1
; 2
; 3
; 4
; Reset!
; 1
;=> 1
こうすることで大域的な名前空間を汚染せずに関数に状態を持たせることができます。