define-syntax

| | コメント(2)

実はSchemeでマクロを一度も書いたことがなかったのでちょっと練習。
マクロ定義はdefine-syntaxで行う。
GaucheではCommon Lispのdefmacroのようなマクロ定義構文として、
define-macroもある。がこっちはR5RS範囲外。


マクロの書き方は次のかたち。
パターンの中で"_"が出てきたらマクロ名、
"..."は可変数の式として解釈します。


(define-syntax マクロ名
  (syntax-rules (キーワードリスト)
    ((パターン1) (マクロ展開後の式))
    ((パターン2) (マクロ展開後の式))
    ...))

1. C#風foreach


(define-syntax foreach
  (syntax-rules (in)
    ((_ elm in lst expr ...)
     (let loop ((l lst))
       (unless (zero? (length l))
               (let ((elm (car l)))
                 expr ...
                 (loop (cdr l))))))))
 
(foreach e in '("1st" "2nd" "3rd")
         (display e)
         (newline))
>1st
>2nd
>3rd

2. Ruby風for


(define-syntax for
  (syntax-rules (= ..)
    ((_ i = from .. to expr ...)
     (let loop ((i from))
       (when (< i to)
             expr ...
             (loop (+ i 1)))))))
 
(for i = 0 .. 5
  (display i))
>01234

あ、なんかこれ楽しいわ。
define-syntaxは読みやすくていいね。
expr ... とか構文定義してる感じで気持ちいい。

コメント(2)

wiz@('A`)・・・ :

_( (_´Д`)_<やっと読めた・・・

Schemeに触れたことはないが、とりあえず、上の例は理解した。

20分くらいかかったな。('A`)マダマダ修行が・・・

最初は、foreachの方だけ見て、

(syntax-rules (= ..)

が、構文定義の部分だと思った。んで、

((_ i = from .. to expr ...)

で、iに..からexpr ...までを入れていると解釈した。

駄菓子菓子(゚Д゚)

それではつじつまが合わない。

そこで、C#風のもあわせて考えてみた。

考えること十数分、やっとパターンの分離に成功した。

((_ i = from .. to expr ...)

ここが構文定義であって、従って最初に書かれた、_はマクロ名になるということは、

((for i = from .. to expr ...)

であり、from や to は、予約語ではなく変数名であろうということに気が付いた。

それに気付けば後は簡単。

ま、細かいところは微妙にすっ飛ばしてるけど。

(+ i 1) が、 i += 1;な感じなのは、アセンブリックと言えそうだが、
括弧が多いし、1行に1命令じゃないので微妙だ。

letの役割とかはまだ分からんが、とりあえず、これ以上時間をかけて分析するなら、
CMSでも作りたいところなんでやめておく。

eclipse :

ちと説明不足でしたな。
でも書いてあることも読んでない気がw
ま触ったことなくてその時間で理解できれば大したもんですね。

このブログ記事について

このページは、yuchが2006年5月17日 15:48に書いたブログ記事です。

ひとつ前のブログ記事は「静止摩擦力」です。

次のブログ記事は「named-let」です。

最近のコンテンツはインデックスページで見られます。過去に書かれたものはアーカイブのページで見られます。

Powered by Movable Type 4.01