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-12-29

KMRCLを眺める (52) (SETF GET-ALIST)

| 01:12 | KMRCLを眺める (52) (SETF GET-ALIST) - わだばLisperになる を含むブックマーク はてなブックマーク - KMRCLを眺める (52) (SETF GET-ALIST) - わだばLisperになる

今回は、KMRCLのlists.lisp中から(SETF GET-ALIST)です。

GET-ALISTのSETTER版といったところ。定義は、

(defun (setf get-alist) (value key alist &key (test #'eql))
  "This won't work if the alist is NIL."
  (update-alist key value alist :test test)
  value)

動作は、

(LET ((AL (COPY-ALIST '((FOO . 1) (BAR . 2) (BAZ . 3)))))
  (SETF (GET-ALIST 'FOO AL) 100)
  AL)
;⇒ ((FOO . 100) (BAR . 2) (BAZ . 3))

前々回のUPDATE-ALISTを利用しています。

UPDATE-ALISTはマクロで定義されていましたが、なぜマクロなのか謎でした。

UPDATE-ALISTのコメントを良く読むと"Macro to support below (setf get-alist)"

とのこと。

なるほど!そういうことか!だからマクロなのか!と思いましたが、

(DEFUN UPDATE-ALIST-FN (AKEY VALUE ALIST &KEY (TEST #'EQL) (KEY #'IDENTITY))
  (LET ((ELEM (ASSOC AKEY ALIST :TEST TEST :KEY KEY))
        (VAL VALUE))
    (COND (ELEM (SETF (CDR ELEM) VAL))
          (ALIST (SETF (CDR (LAST ALIST)) (LIST (CONS AKEY VAL))))
          (T (SETF ALIST (LIST (CONS AKEY VAL)))))
    ALIST))

(DEFUN (SETF GET-ALIST-FN) (VALUE KEY ALIST &KEY (TEST #'EQL))
  (UPDATE-ALIST-FN KEY VALUE ALIST :TEST TEST)
  VALUE)

(LET ((AL (COPY-ALIST '((FOO . 1) (BAR . 2) (BAZ . 3)))))
  (SETF (GET-ALIST-FN 'FOO AL) 100)
  AL)
;⇒ ((FOO . 100) (BAR . 2) (BAZ . 3))

いや、やっぱり関数で良いんじゃないかと…。

いまいち自分は、(DEFUN (SETF ...))、DEFSETF、DEFINE-SETF-EXPANDERの使い分けに迷いますが、DEFSETFだと

(DEFSETF GET-ALIST-FN2 (KEY ALIST) (VAL)
  `(UPDATE-ALIST-FN ,KEY ,VAL ,ALIST))

(LET ((AL (COPY-ALIST '((FOO . 1) (BAR . 2) (BAZ . 3)))))
  (SETF (GET-ALIST-FN2 'FOO AL) 100)
  AL)
;⇒ ((FOO . 100) (BAR . 2) (BAZ . 3))

とも書けます。

ゲスト



トラックバック - http://cadr.g.hatena.ne.jp/g000001/20091229