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)))