#:g1: fare-quasiquoteの紹介

Posted 2014-01-29 15:00:00 GMT

(LISP Library 365参加エントリ)

 LISP Library 365 の30日目です。

fare-quasiquoteとはなにか

 fare-quasiquoteは、Scheme方式のQuasiquoteをCommon Lispに導入するものです。

パッケージ情報

パッケージ名fare-quasiquote
Quicklisp
CLiKihttp://cliki.net/fare-quasiquote
Quickdocshttp://quickdocs.org/fare-quasiquote

インストール方法

(ql:quickload :fare-quasiquote)

試してみる

 どんな関数があるかは、Quickdocsで確認できます。

 SchemeのQuasiquoteをCommon Lispに導入するそもそもの動機は、パターンマッチで`(,x ,y)を使いたかったということのようです。
具体的には、Schemeのmatchでの

(match '(1 2 3)
  (`(,x 5 ,z) (list x y z))
  (`(,x 2 ,z) (list :win x 2 z)))
;=> (:win 1 2 3)

のようなものだと思われます。Common Lispのバッククォートは、リード時に展開されてしまい展開結果も処理系によってまちまちだったりするのですが、展開形が統一されていないとパターンマッチでは色々と不便です。
ということで、fare-quasiquoteには、fare-macherや、optimaと組み合わせて使うユーティリティも付属してきます。
下記の例は、optimaと組み合せて利用する例です。

(ql:quickload :optima)
(ql:quickload :named-readtables)

;; 利用するリードテーブルを変更 (named-readtables:in-readtable :fare-quasiquote)

(optima:match '(1 2 3) ((list x y z) (list x y z))) ;=> (1 2 3)

(optima:match '(1 2 3) (`(,x ,y ,z) (list x y z))) ;=> (1 2 3)

(optima:match '(1 2 3) (`(,x 5 ,z) (list x y z))) ;=> NIL

(optima:match '(1 2 3) (`(,x 5 ,z) (list x y z)) (`(,x 2 ,z) (list :win x 2 z))) ;=> (:WIN 1 2 3)

 また、表示の設定がされていないと、

(let* ((x 1)
       (xx `(,x ,x ,x))
       (qx '`(,x ,x ,x)))
  (list xx qx))
;=>  ((1 1 1) (FARE-QUASIQUOTE::LIST X X X))

のようなことになりますが、(fare-quasiquote:enable-qq-pp)することで

(let* ((x 1)
       (xx `(,x ,x ,x))
       (qx '`(,x ,x ,x)))
  (list xx qx))
;=>  ((1 1 1) `(,X ,X ,X))

と表示されるようになります。
ちなみに、Schemeのようにunquoteを取り出すことはできないようなので、SchemeのQuasiquoteそのままの動作ではないようです。

(list ',x)
;!! unquote outside quasiquote

;;; schemeの場合
(list ',x)
;=>  (,x)

fare-quasiquoteの紹介/関連記事等

まとめ

 今回は、fare-quasiquoteを紹介してみました。
自分もSchemeのmatchをCommon Lispに移植して利用していますが、やはりScheme方式のQuasiquoteを導入して使っています。
リードテーブルを触るのはちょっと…という人も多いかなと思いますが便利な時は便利かなと思います。

comments powered by Disqus