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 |

2010-01-03

Clojure 1.1のdo-templateをCLで

| 03:22 | Clojure 1.1のdo-templateをCLで - わだばLisperになる を含むブックマーク はてなブックマーク - Clojure 1.1のdo-templateをCLで - わだばLisperになる

no titleを観てみると、Clojure 1.1には色々と機能が追加されたみたいようです。

4つ位機能が紹介されていますが、do-templateはCommon Lispですぐ真似できそうだったので早速マクロを書いてみました。

(USE-PACKAGE :SHIBUYA.LISP)

(DEFUN SUBST* (NEWS OLDS TREE &KEY (TEST #'EQL TESTP) 
                                   (TEST-NOT #'EQL NOTP))
  (WHEN (AND TESTP NOTP)
    (ERROR ":TEST and :TEST-NOT were both supplied."))
  (IF (OR (ENDP NEWS) (ENDP OLDS))
      TREE
      (SUBST* (CDR NEWS) (CDR OLDS)
              (APPLY #'SUBST (CAR NEWS) (CAR OLDS) 
                     TREE (IF NOTP 
                              (LIST :TEST-NOT TEST-NOT)
                              (LIST :TEST TEST))))))

(DEFMACRO DO-TEMPLATE ((&REST VARS) EXPR &REST VALS)
  `(PROGN ,@(MAPCAR (CUT SUBST* <> VARS EXPR)
                    (GROUP VALS (LENGTH VARS)))))

使い方は、

(DO-TEMPLATE (NAME INC)

  (DEFUN NAME (N)
    (+ N INC))
  
  FOO 2
  BAR 3
  BAZ 4)

とテンプレートの定義を書くと、

(PROGN
  (DEFUN FOO (N) (+ N 2))
  (DEFUN BAR (N) (+ N 3))
  (DEFUN BAZ (N) (+ N 4)))

と展開されます。

マクロがあるのに、なんでわざわざという気もしますが、マクロのデザイン・パターンの一つとして考えれば、こういうのも悪くないかなと思いました。

Common Lispでは、do-templateは、

(MACROLET ((DE (NAME INC)
             `(DEFUN ,NAME (N)
                (+ N ,INC))))
  (DE FOO 2)
  (DE BAR 3)
  (DE BAZ 4))

とでも書けるかなと思います。