by shigemk2

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

リスト遊び 8-5 置換!

前回
リスト遊び 8-4 ゴミ集め - by shigemk2

以前のやつは3つくらい変数を生成していて、明らかにリソースの無駄だったので、
新しいリストを生成せずに、副作用を利用して引数に取ったリストそのものを
反転させる。
これでリソースを節約できる。

引数(リスト)の中身を逆転させる関数

(defun nreverse (lst)
  (let ((this lst) prev next)
    (while this
      ;; thisのcdrをnextに保存している
      (setq next (cdr this))
      ;; thisが指しているセルのCDRに、prevが指しているセルを
      ;; 参照させる(逆転作業をこちらで行う)。初期はnil
      (setcdr this prev)
      ;; 次のprevとthisへ
      (setq prev this)
      (setq this next))
    prev))
nreverse
(nreverse '(1 2 3))
(3 2 1)

repl III改
最後のリスト逆転を、nreserveに任せる

(defun repl (lst old new)
  (let (ret)
    (while lst
      (cond
       ((eq old (car lst))
	(setq ret (cons new ret)))
       (t (setq ret (cons (car lst) ret))))
      (setq lst (cdr lst)))
    (nreverse ret)))
repl
(repl '(1 2 3) 3 2)
(1 2 2)

nreverseには副作用があるが、replには副作用がないことに
注意する。

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

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