listを一連の流れの連鎖ではなく候補からの選択と捉えてみると…
listを一連の流れの連鎖ではなく候補からの選択と捉えてみると、別な形のマクロが思い浮かぶ。
(やり過ぎ良くない…ただ、実験ということで)
例えば、こんな感じ。clojureの->,->>にならい、初期値を取りそれをもとに選択を行うようになっている。
(define (f x p val) (and (p x) val)) (define (QandA Q) (@maybeL Q (f symbol? 'symbol) (f integer? 'int) (f list? 'list) (f identity 'unknown))) (map QandA '(10 aa (aa) #(aa))) ; => (int symbol list unknown)
他の構文とは異質なものなので、それをはっきりさせるために@をつけている。
code
(use util.match) (define-macro (@maybeL init . candidates) (let ((tmp (gensym))) `(let1 ,tmp ,init (or ,@(map (match-lambda [(fn . args) `(,fn ,tmp ,@args)] [fn `(,fn ,tmp)]) candidates))))) (define-macro (@maybeR init . candidates) (let ((tmp (gensym))) `(let1 ,tmp ,init (or ,@(map (match-lambda [(fn . args) `(,fn ,@(append args (list tmp)))] [fn `(,fn ,tmp)]) candidates))))) (define-macro (@allL init . candidates) (let ((tmp (gensym))) `(let1 ,tmp ,init (and ,@(map (match-lambda [(fn . args) `(,fn ,tmp ,@args)] [fn `(,fn ,tmp)]) candidates))))) (define-macro (@allR init . candidates) (let ((tmp (gensym))) `(let1 ,tmp ,init (and ,@(map (match-lambda [(fn . args) `(,fn ,@(append args (list tmp)))] [fn `(,fn ,tmp)]) candidates)))))
@maybeLがあるとfizzbuzzが以下のように書ける。(意味があるかは知らない)
fizzbuzz
(define (f n x val) (and (zero? (modulo n x)) val)) (dotimes (i 100) (print (@maybeL k (f 15 'fizzbuzz) (f 3 'fizz) (f 5 'buzz) identity)))