syntax-caseでどう書く?的

"Scheme どう書く?的 - ひげぽん OSとか作っちゃうかMona-トラックバックを見ていたら・・・Scheme どう書く?的をScalaで書いてみた - 玲瓏庵にあるScalaのコードが羨ましかったので、ひげぽんさんの所のコメント欄に入れたコードを少しおしゃれに書き直してみる。む〜、これ以上は何かマクロを作らないと無理かな〜

;; datum definition from Chez Scheme User's Guide
(define-syntax datum (syntax-rules () [(_ t) (syntax->datum (syntax t))]))

(define (compact-number-list x)
  (let loop ((x (cons '[] x)))
    (syntax-case x ()
      (([(lo . hi) r ...] new more ...)
       (if (= (datum new) (+ (datum hi) 1))
           (loop (datum ([(lo . new) r ...] more ...)))
           (loop (datum ([(new . new) (lo . hi) r ...] more ...)))))
      (([] new more ...) (loop (datum ([(new . new)] more ... ))))
      ((ans) (reverse (map (lambda (e) (if (= (car e) (cdr e)) (car e) e)) 
                           (datum ans)))))))

(compact-number-list '(1 3 4 5 6 12 13 15))
=> (1 (3 . 6) (12 . 13) 15)

ちなみに元のコードはこれです。

(define (compact-number-list x)
  (define (test e1 e2)
    (= (syntax->datum e1) (+ (syntax->datum e2) 1)))
  (let loop ((x (cons '[] x)))
    (syntax-case x ()
      (([(lo . hi) r ...] new more ...)
       (if (test #'new #'hi)
           (loop (syntax->datum #'([(lo . new) r ...] more ...)))
           (loop (syntax->datum #'([new (lo . hi) r ...] more ...)))))
      (([lo r ...] new more ... )
       (if (test #'new #'lo)
           (loop (syntax->datum #'([(lo . new) r ...] more ... )))
           (loop (syntax->datum #'([new lo r ...] more ... )))))
      (([] new more ...)
       (loop (syntax->datum #'([new] more ... ))))
      ((ans)
       (reverse #'ans)))))

注意:ここに書いたコードは実行時にマクロ展開を行うので速度は期待できません。