Shammer's Philosophy

My private adversaria

Lisp の mapc 関数

mapc 関数は、mapcar 関数と似ている。引数で渡されたリストに対して、指定された処理を繰り返す、というものだが、新しいリストを返さない、という点が異なる。

? (defun mapcar-test (lst)
    (if (listp lst)
        (mapcar #'(lambda (x) (concatenate 'string "Hello, " x)) lst)
        (format t "Usage: mapcar-test $LIST~%")))
MAPCAR-TEST
? (setf x '("Mr. Brown " "Mr. White"))
("Mr.Brown" "Mr.White")
? (mapcar-test x)
("Hello, Mr.Brown" "Hello, Mr.White")
? x
("Mr.Brown" "Mr.White")

mapcar は、引数の内容が処理の前後で変わらない。
mapc は、以下のようになる。

? (defun mapc-test (lst)
  (if (listp lst)
      (mapc #'(lambda (x) (concatenate 'string "Good-bye, " x)) lst)
    (format t "Usage: mapc-test $LIST~%")))
MAPC-TEST
? (mapc-test x)
("Mr.Brown" "Mr.White")

しまった・・・この例じゃよくわからないかも。関数の仕様的には、mapc は返り値のリストを新しく作らない、というものだが、それを確認できない。
これを確認するためには・・・

? (setf x '("A" "B"))
("A" "B")
? (setf result01 (mapc #'(lambda (xx) (concatenate 'string "Good-bye, " xx)) x))
("A" "B")
? (eql x result01)
T

最初のリスト(x)と、mapc の結果返されたリストが等しい(同じリスト)ことがわかる。
これを、mapcar でやってみると、

? (setf z '("X" "Y"))
("X" "Y")
? (setf result02 (mapcar #'(lambda (aa) (concatenate 'string "Yes, " aa)) z))
("Yes, X" "Yes, Y")
? (eql z result02)
NIL

mapc は、返り値が引数と同じリスト。それに対して、mapcar は異なるリストが返っている。