On Lisp 復習

自分用メモのつづき。(d:id:Nobuhisa:20080114:1200338245)
ようやく4章のコードひと通り復習でけたー。(掲載するのは一部)

4.5 マッピング (ま!ピングー!)

CL-USER 1 >
(defun map-> (fn start test-fn succ-fn)
  (do ((i start (funcall succ-fn i)) (result nil))
      ((funcall test-fn i) (nreverse result))
    (push (funcall fn i) result) ))
MAP->

CL-USER 2 > 
(defun mapa-b (fn a b &optional (step 1))
  (map-> fn
         a
         #'(lambda (x) (> x b))
         #'(lambda (x) (+ x step)) ))
MAPA-B

CL-USER 3 > 
(defun map0-n (fn n)
  (mapa-b fn 0 n) )
MAP0-N

CL-USER 4 > (map0-n #'(lambda (x) (expt 2 x)) 10)
(1 2 4 8 16 32 64 128 256 512 1024)

CL-USER 5 > (mapa-b #'1+ -2 0 0.5)
(-1 -0.5 0.0 0.5 1.0)

文中に,CLTL2で追加されたシリーズマクロを使って置き換えた例があったんですが,

(mapa-b #'foo a b c);;before
(collect (#Mfoo (scan-range :from a :upto b :by c)));;after

なんかうまく行きませんでした。(環境:LispWorks Personal)
そもそもシリーズマクロというものがまだ何者か良く知らないので,これについては今後の課題ということにしておきましょう・・・。


マッピングつづき

CL-USER 1 > 
(defun rmapcar (fn &rest args)
  (if (some #'atom args)
      (apply fn args)
    (apply #'mapcar
           #'(lambda (&rest args)
               (apply #'rmapcar fn args))
           args) ))
RMAPCAR

CL-USER 2 > (rmapcar #'+ '(1 (2 (3) 4)) '(10 (20 (30) 40)))
(11 (22 (33) 44))

分かったような分かってないような・・・(´_`)修行が足りないですね。。
あと,some関数というものを初めて知った。第二引数のシーケンスを先頭から見ていって,誰かが非nilを返すとそれが返ってくる。全員nilの場合はnilが返ってくる。
他にeveryという関数もあった。 これは全員が非nilを返すとtを返す。一人でも裏切り者がいればnilが返ってくる。
rmapcar関数は要復習ということで。。。

4.7 シンボルと文字列

シンプルだけどこれはなかなか便利かも

CL-USER 1 > 
(defun mkstr (&rest args)
  (with-output-to-string (s)
    (dolist (a args)
      (princ a s) )))
MKSTR

CL-USER 2 > (mkstr pi " pieces of " 'pi)
"3.141592653589793D0 pieces of PI"

あと,シンボルの印字名に記号とか使う際の特殊な表記を知った。
特殊な文字の前に\をつけるか,全体を||で囲う。

CL-USER 1 > (set '\(a\ b\) 256)
256

CL-USER 2 > |(a b)|
256

CL-USER 3 > (setq |(^ o ^)| 1024)
1024

CL-USER 4 > |(^ o ^)|
1024


最後。シンボルを分解してリストにして返す。

CL-USER 1 > 
(defun explode (s)
  (map 'list
       #'(lambda (c)
           (intern (make-string 1 :initial-element c)) )
       (symbol-name s) ))
EXPLODE

CL-USER 2 > (explode 'PaulGraham)
(P A U L G R A H A M)

昔の方言では組み込み関数として存在していたそうですが,そもそもシンボルを分解する時は大抵非効率的な作業をしていることが多い(?)とのことでCommon Lispには入らなかったらしい。(P59)
いまいち良く分からないけど,確かにシンボルを分解することは少なそう。 でもこういう変なことが普通に出来るのでLispって面白い。笑


何箇所か復習の余地がありますが,4章のユーティリティは一通り理解できたかな。 ユーティリティ書くのって一般的に難しいけど(汎用性やら効率やら),面白いかもしれない。
後半出てきた関数は見覚えがないものとかあったので,入院中にOn Lisp読んだ時は軽く目を通して飛ばしてたのかもしれない。。(実行環境や知らない関数を調べる手段がなかったので...)