R6RS Scheme で Erlang のビット構文

Erlang にはビット構文という素敵な仕組みがあって、簡単に pack/unpack することができる。

1> Color = <<Red:5,Green:6,:Blue:5>>.
2> <<R:5, G:6, B:5>> = C.

こういうの。


直感的で分かりやすくてうらやましい。Scheme ならマクロで書けそうだなと思い。unpack だけ簡単なものを書いてみました。
途中で面倒になって汎用版は投げ出してしまった。
当然ながら今は、最適化とかしていないので遅いのだけど、やっぱり読みやすい。ネットワークパケットとかと相性が良かったりしないかな?
ちゃんとしたものを書いて、comp.lang.scheme に投稿してみるのも面白いかも。

(import (rnrs)
        (srfi :64))

(define-syntax :bit
  (lambda (x)
    (syntax-case x ()
      [(_ ([a m] [b n]) v body ...)
       (and (fixnum? (syntax->datum #'m)) (fixnum? (syntax->datum #'n))
            (zero? (mod (+ (syntax->datum #'m) (syntax->datum #'n)) 8)))
       #'(let ([bits (+ n m)])
           (let ([a (bitwise-arithmetic-shift-right v (- bits m))]
                 [b (bitwise-and v (- (expt 2 n) 1))])
             body ...))])))

(test-begin "Example of the bit syntax")

;; unpack
(:bit ([x 2] [y 6]) #b10101110
  (test-eqv 2 x)
  (test-eqv 46 y))

(test-end)

追記

id:leque さんが汎用版を書いてくださいました。
Scheme で Erlang のビット構文 - 月の塵
let-bit というネーミングセンスが良いですねー。