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 |

2009-11-14

KMRCLを眺める (12) acond2

| 03:04 | KMRCLを眺める (12) acond2 - わだばLisperになる を含むブックマーク はてなブックマーク - KMRCLを眺める (12) acond2 - わだばLisperになる

今日は、KMRCLのmacros.lispの中からACOND2です。

名前の通りAIF2のCOND版です。述語部で2値を処理できるし、SchemeのSRFI-61の拡張condようなことができるかも、と思いちょっとコード例を考えてみましたが、良く良く考えるとSRFI-61とは全然別ものでした。SRFI-61便利ですね。しょうがないので

(LET ((HT (MAKE-HASH-TABLE)))
  (SETF (GETHASH :BAR HT) NIL
        (GETHASH :BAZ HT) NIL)
  
  (ACOND2 ((GETHASH :FOO HT) (LIST :FOO IT))
          ((GETHASH :BAR HT) (LIST :BAR IT))
          ((GETHASH :BAZ HT) (LIST :BAZ IT))
          ('T :NOT-FOUND)))
;=> (:BAR NIL)

というものを無理矢理考えてみました。

ACOND2の定義はこんな感じです。

(defmacro acond2 (&rest clauses)
  (if (null clauses)
      nil
      (let ((cl1 (car clauses))
            (val (gensym))
            (win (gensym)))
        `(multiple-value-bind (,val ,win) ,(car cl1)
           (if (or ,val ,win)
               (let ((it ,val)) ,@(cdr cl1))
               (acond2 ,@(cdr clauses)))))))

これまで紹介したアナフォリック・マクロが全部合体したような感じですね。

ACOND2の話には全く関係ないのですが、CONDでは述部の返り値が式の返り値になる場合があるというのは以前ACONDのときに書きました。

(COND (:FOO))
;=> :FOO

のような場合ですが、こういうパターンで述語が多値を返す場合はどうなるかというと、

(COND ((VALUES :FOO :BAR)))
;=> :FOO

1番目の値しか返らないと仕様で決まっています。

CONDは詳しく眺めると色々とややこしいところがある気がします。

この述語の多値問題については、上述のSRFI-61は多値も扱えるようになっていて便利ですね。