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

CLでClojureのキーワードが関数(マクロ)になってる風

| 00:10 | CLでClojureのキーワードが関数(マクロ)になってる風 - わだばLisperになる を含むブックマーク はてなブックマーク - CLでClojureのキーワードが関数(マクロ)になってる風 - わだばLisperになる

Clojureでは、ハッシュのキーが値を取り出す関数のような振舞いをするのが便利ですが、仕事帰りの電車でぼーっとしていたら、そういう感じに書けるようなマクロが思い浮かんだので書いてみました。

大雑把に、見付けたキーワードには全部関数を詰めています。

できれば、fletでローカル関数にしたかったのですが、setfで便利に展開してくれるのでmacroletにしときました。

ローカルのsetf関数を書く方法ってあったりするんでしょうか。

(IMPORT 'KMRCL:FLATTEN)

(DEFMACRO WITH-KEYWORD-FUNCTION (&BODY BODY)
  (LET ((KEYS (COLLECT-KEYWORD-SYMBOL BODY)))
    `(MACROLET (,@(MAPCAR (LAMBDA (K)
                             `(,K (HASH-TABLE &OPTIONAL DEFAULT)
                                 `(GETHASH ,',K ,HASH-TABLE ,DEFAULT)))
                          KEYS))
       ,@BODY)))

(DEFUN COLLECT-KEYWORD-SYMBOL (LIST)
  (REMOVE-DUPLICATES
   (REMOVE-IF-NOT #'KEYWORDP (FLATTEN LIST))))
  • 動作
(LET ((TAB (MAKE-HASH-TABLE)))
  (SETF (GETHASH :FOO TAB) 0
        (GETHASH :BAR TAB) 0
        (GETHASH :BAZ TAB) 0)
  (WITH-KEYWORD-FUNCTION
    ;; 値を再度設定
    (SETF (:FOO TAB) 66
          (:BAR TAB) 77
          (:BAZ TAB) 88)
    ;; 値を確認
    (LIST (:FOO TAB)
          (:BAR TAB)
          (:BAZ TAB))))
;⇒ (66 77 88)