gauche util.match メモ
gauche の util.match で、束縛する必要が無いパターンには「_」を使うとよいことを shiro さんに教えていただいた。
(http://practical-scheme.net/chaton/gauche/a/2010/05/30 あたり)
util.match のリファレンスはこちら。
http://practical-scheme.net/gauche/man/gauche-refj_164.html#SEC466
「_」を使うとどのくらい違うかを手元のコードで比較してみた。
(define m (macroexpand '(match (list s e c d val) ((s e #((:CONST) n rest ...) d val) (vmloop s e (+ pc 2) d n)) ((s e #((:CONSTI n) rest ...) d val) (vmloop s e (+ pc 1) d n)) ((s e #((:CONSTI-PUSH n) rest ...) d val) (vmloop (cons n s) e (+ pc 1) d val)) ((s e #((:GREF) var rest ...) d val) (vmloop s e (+ pc 2) d (lookup-global var))) ((s e #((:PUSH) rest ...) d val) (vmloop (cons val s) e (+ pc 1) d val)) ((s e #((:NUMADDI num) rest ...) d val) (vmloop s e (+ pc 1) d (+ num val))) ((s e #((:NUMSUBI num) rest ...) d val) (vmloop s e (+ pc 1) d (- num val))) (((v . s) e #((:NUMMUL2) rest ...) d val) (vmloop s e (+ pc 1) d (* v val))) (((a . s) e #((:BNGT) then rest ...) d val) (if (> val a) (vmloop s e then d val) (vmloop s e (+ pc 2) d val))) ((s e #((:CLOSURE) body rest ...) d val) ;; todo (vmloop () e (+ pc 2) d (cons e body))) ((s e #((:PRE-CALL procedure-id) location rest ...) d val) (vmloop s e (+ pc 2) (cons (cons location val) d) val)) ((s e #((:RET) rest ...) d val) ;; todo #f ) ((s e c d val) (format #t ";; base case: s: ~s e: ~s c: ~s d: ~s val: ~s pc: ~s~%" s e (subseq c 0 1) d val pc)) ))) (define m_ (macroexpand '(match (list s e c d val) ((s e #((:CONST) n _ ...) d val) (vmloop s e (+ pc 2) d n)) ((s e #((:CONSTI n) _ ...) d val) (vmloop s e (+ pc 1) d n)) ((s e #((:CONSTI-PUSH n) _ ...) d val) (vmloop (cons n s) e (+ pc 1) d val)) ((s e #((:GREF) var _ ...) d val) (vmloop s e (+ pc 2) d (lookup-global var))) ((s e #((:PUSH) _ ...) d val) (vmloop (cons val s) e (+ pc 1) d val)) ((s e #((:NUMADDI num) _ ...) d val) (vmloop s e (+ pc 1) d (+ num val))) ((s e #((:NUMSUBI num) _ ...) d val) (vmloop s e (+ pc 1) d (- num val))) (((v . s) e #((:NUMMUL2) _ ...) d val) (vmloop s e (+ pc 1) d (* v val))) (((a . s) e #((:BNGT) then _ ...) d val) (if (> val a) (vmloop s e then d val) (vmloop s e (+ pc 2) d val))) ((s e #((:CLOSURE) body _ ...) d val) ;; todo (vmloop () e (+ pc 2) d (cons e body))) ((s e #((:PRE-CALL procedure-id) location _ ...) d val) (vmloop s e (+ pc 2) (cons (cons location val) d) val)) ((s e #((:RET) _ ...) d val) ;; todo #f ) ((s e c d val) (format #t ";; base case: s: ~s e: ~s c: ~s d: ~s val: ~s pc: ~s~%" s e (subseq c 0 1) d val pc)) )))
m は(無駄に)rest を使っているもの、m_ は「_」を使って改善したもの。m はかなり巨大な、ちょっと pretty print などで表示するのもためらわれる大きさになっている。flatten で要素に分解して数えてみると、以下のように大きな差が出る。
gosh> (length (flatten m)) 513176 gosh> (length (flatten m_)) 991
パターンマッチマクロは便利なので、ちゃんとリファレンスマニュアルを読んで適切に使おう。