Hatena::Groupcadr

わだばLisperになる このページをアンテナに追加 RSSフィード

2004 | 12 |
2005 | 01 | 02 | 07 | 10 | 11 |
2006 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2007 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2008 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2009 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2010 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2011 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 11 |

2007-10-18

Lisppasteからの漂着物(unzipcan)

| 02:46 | Lisppasteからの漂着物(unzipcan) - わだばLisperになる を含むブックマーク はてなブックマーク - Lisppasteからの漂着物(unzipcan) - わだばLisperになる

とりあえずコードを読むことは日課にしたいところなので、量は少なくとも毎日更新して行くことを目標としました。

今日は、気力が出ないので、LisppasteのRSSをチェックしていて気になったものに挑戦。

Paste number 49158: unzipcan Pasted by: kpreid

コードの作者は、kpreid氏です。

お題

(defun unzipcan (operation list)
  "Call OPERATION for each element of LIST, destructively concatenating its two return values into two result lists."
  (loop with x and y
        for item in list
        do (setf (values x y) (funcall operation item))
        nconc x into xs
        nconc y into ys
        finally (return (values xs ys))))

暗記で再現:失敗

(defun unzipcan (operation list)
  (loop :with x :and y
        :for item :in list
        :do (setf (values x y) (funcall operation item))
        :nconc x :into xs
        :nconc y :into ys
        :finally (values xs ys)))

finally節で、returnを忘れてしまった…。もっとloopに親しまないといけないなという感じ。

ちなみに、doだと、

(defun unzipcan (operation list)
  (do ((item list (cdr item))
       x y 
       (xs (list ()))
       (ys (list ())))
      ((endp item) (values (cdr xs) (cdr ys)))
    (setf (values x y) (funcall operation (car item)))
    (nconc xs x)
    (nconc ys y)))

みたいな感じでしょうか…。

ループのキーワードがキーワードなのは、こういう風に書いている人がいて、こっちの方がキーワードっぽくて自分には読みやすかったのて真似してみました。

どうしてこれをお題をしたかというと、(setf (values x y) (funcall operation item))っていうところを読んて、setfにvaluesとか使えることを初めて知ったので記念に取り上げてみました。

まあ、multiple-value-setqとかありますが…。戻り値が多値と単一だったり微妙に動作が違ってはいたりはします。

このunzipcanの動作については良く分からず、

(unzipcan (lambda (x) (list (apply #'floor x))) '((2 1) (4 3) (6 5) (8 7)))

とか

(unzipcan (lambda (x) (values `(,(car x)) `(,(cadr x)))) '((2 1) (4 3) (6 5) (8 7)))

とかするんでしょうか。

mapcan的なunzipってのは分かるんですが…。