by shigemk2

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

リスト遊び 5-2 置換*

前回
リスト遊び 5-1 再帰の再帰 - by shigemk2

replを拡張して、入れ子のリストも取扱えるrepl*を実装してみる。
リストの先頭の要素がリストである場合には、その内側リストと共に
repl*を呼び出し、oldをnewに置き換える。そしてリストの残りに対しても
repl*を呼び出す。repl*が返すのはリストだから、前者を後者にconsするとよい。
リストにconsしているから、どれだけ複雑なリスト構造でも構造を全く破壊せずに
アトム部分だけを置換できる。

(defun repl (lst old new)
  (cond
   ((null lst) nil)
   ((eq (car lst) old)
    (cons new (repl (cdr lst) old new)))
   (t (cons (car lst) (repl (cdr lst) old new)))))
repl
(repl '(1 2 3) 1 2)
(2 2 3)

(defun repl* (lst old new)
  (cond
   ((null lst) nil)
   ((consp (car lst))
    (cons (repl* (car lst) old new)
	  (repl* (cdr lst) old new)))
   ((eq (car lst) old)
    (cons new (repl* (cdr lst) old new)))
   (t (cons (car lst) (repl* (cdr lst) old new)))))
repl*

(repl* '((1 1) 2 3) 1 2)
((2 2) 2 3)

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

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