最近define-macroでごちゃごちゃS式をいじることを試しています。
渡された引数をお手軽に処理してみたくて、util.matchを使ってみようとした。
(region (width 210mm) (height 297mm)) ...中略 (make <region> :width 210 :height 297)
やりたいことは上記みたいに展開してみること。
ミニ言語とか埋め込み言語とか言ったりするものなのかな。
(define func (match-lambda (((key val) ...) (format "key=~s val=~s" key val)) (_ (format "error"))))
まずはkeyとvalの繰り返しにマッチさせることを考えてみた。
以下のような感じでkeyとvalにマッチさせることができます。
(func '((a b) (c d) (e f))) =>gosh> "key=(a c e) val=(b d f)"
これができれば、keyのそれぞれにmake-keywordを適用してスロットの初期化指定のリストに変換してやれば
インスタンスを(regionを記述するだけで生成させるようなS式に変換できる。
(func '((a b) (c d) (e (f g)) (h i))) =>gosh> "key=(a c e h) val=(b d (f g) i)"
この定義ならkey eに対応するvalがリスト(f g)でも良い。
(func '((a b) (c d) (e (f g) (h i)))) =>gosh> "error"
けれども、valが(f g) (h i)のような場合に失敗してしまう。
例えば、(page 以降の部分にマッチさせようとしても、errorになる。
(page (width 210) (height 297) (region (width 210) (height 297)))
さて、こういうときはパターンをどう記述するのがいいんだろうか。
(define func (match-lambda ((key ((key2 val2) ...)) (format "key=~s key2=~s val2=~s" key key2 val2)) (((key val) ...) (format "key=~s val=~s" key val)) (_ (format "error"))))
とすればいいのかと思ったけど違うらしい。