Gaucheのutil.matchを勉強してみる

とりあえずはこんなかんじらしい

>> (match '(1 2 3) ((a b c) (list a b c)))
=> (1 2 3)

>> (match '(1 (2 3)) ((a (b c)) (list a b c)))
=> (1 2 3)

つぎに、リスト処理させてみる

>>(match '(1 2 3 4) ((x . xs) (print x)))
1
=>#<undef>

>>(match '(1 2 3 4) ((x . xs) (print xs)))
(2 3 4)

なるほど。こりゃおもしろい。

>>((match-lambda ((x . xs) xs)) '(1 2 3 4))
=>(2 3 4)

おお、括弧がひとつ削れるのか。

>>((lambda (a) (match a ((x . xs) xs)))  '(1 2 3 4))
=>(2 3 4)

こいつと同じと。確かに短くなってる(笑

で、変なのがあったのでそいつを実験

>>(match-lambda (() '()))
=>#<closure #f>

>>(lambda (x) (match x (() '())))
=>#<closure #f>

>>((lambda (x) (match x (() '()))) ())
=>()

なるほどー。すごいなこりゃ。

並列で書いてあるのでそこを実験

>>((match-lambda (() "null") ((x . xs) xs)) ())
=>null

>>((match-lambda (() "null") ((x . xs) xs)) '(1 2 3))
=>(2 3)

おお、null?時のifを一つ省略できる。

ってことで、match-lambdaを使ってクイックソートを書き直してみた

>>(define qsort (match-lambda (()()) ((x . xs) (receive (l r) (partition (lambda (y) (< y x)) xs) (append (qsort l) (list x) (qsort r))))))
=>qsort

>>(qsort '(4 3 5 2 5 2 3 4))
=>(2 2 3 3 4 4 5 5)

よし。後はcutと準クオートだ。
ifがなくなるのは良い記法だなー

以下のように木構造をきれいに辿れるらしい。

(define (walk func tree)
         (match tree
               [() '()]
               [(x . xs) `(,(walk func x) . ,(walk func xs))]
               [x (func x)] ))
-->walk
(walk (lambda (x) (+ x 1)) '(1 2 (3 4 (5)) 6))
-->(2 3 (4 5 (6)) 7)