これぞまさしく for を使いたい場面が出てきたのだけれど、 Gauche には for がないので作ってみました。基本的にはこんな感じで使うイメージです:

(for (i 1 10) (print i))

条件が成立している場合にだけ、「(print i)」を評価したいから、こういう場合はマクロを使うんだよね。たしか。

作成に当たっては、「define-syntax | METAMATE」を参考にしたよ:

マクロ定義はdefine-syntaxで行う。

GaucheではCommon Lispのdefmacroのようなマクロ定義構文として、

define-macroもある。がこっちはR5RS範囲外。

マクロの書き方は次のかたち。

パターンの中で”_”が出てきたらマクロ名、

“…”は可変数の式として解釈します。

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

define-syntax | METAMATE

ソース

(define-syntax for
(syntax-rules (by)
[(for (i init limit by step) expr ...)
(do ((tlimit limit)
(i init (+ i step)))
((> i tlimit))
expr ...)]
[(for (i init limit) expr ...)
(do ((tlimit limit)
(i init (+ i 1)))
((> i tlimit))
expr ...)]))

「syntax-rules (by)」とすることで「by」が特別扱いされる…ようだ。

実行例

gosh> (for (i 1 10) (print "foo"))
foo
foo
foo
foo
foo
foo
foo
foo
foo
foo
#t
gosh> (for (i 1 10) (print i))
1
2
3
4
5
6
7
8
9
10
#t
gosh> (for (i 1 10 by 5) (print i))
1
6
#t