パターンマッチ

組み込みのappend関数を実装すると次のようになる。

(define my-append
  (lambda args
    (cond
     ((null? args) '())
     ((null? (cdr args)) (car args))
     (else (append2 (car args) (apply my-append (cdr args)))))))

(define append2
  (lambda (a b)
    (if (null? a)
	b
	(cons (car a) (append2 (cdr a) b)))))

append2は引数で受け取った2個のリストをつなげる関数。


my-appendで重要な点は、可変長引数argsが

  • 空リスト
  • 要素1個
  • それ以外

のどれにマッチするか調べるところ。
上のように書くのは長くなるので、次のようにmatch構文を使うと簡単に書けるらしい。

(define my-append
  (lambda args
    (match args
      (() '())
      ((a) a)
      ((a . b) (append2 a (apply my-append b))))))

match構文を使うには、事前に

(use util.match)

しとかないといけないらしい。

match構文は、

(match <式>
  (<パターン1> <<式>がパターン1にマッチしたときの値>)
  (<パターン2> <<式>がパターン2にマッチしたときの値>)
  ...
  (<パターンn> <<式>がパターンnにマッチしたときの値>))

ってな形をしてて、<パターンi>にはいろんな高度な方法があるらしい。
今んとこは

  • ()が空リスト
  • (a)が要素1個のリスト
  • (a . b)が要素2個以上のリストまたはドット対

ってだけ覚えておこう。


使ってみて便利だなぁと思ったところは、パターンマッチングしつつ、名前を束縛できるところかな。