Let's start Scheme

2011-07-12

R6RSのレコードにあるprotocolが地味に便利だった件

あまりに複雑すぎる(とどっかで見た)と不評なR6RSのレコードだが、単に使うだけなら結構便利な件。
特に今までつかってなかったけど、protocolが結構便利。
例えばこんな例:
(define-record-type something
  (fields (mutable f1)
          (mutable f2)
          (mutable f3)))
上記のレコードsomethingはfieldsとしてf1~f3まで持つけど、初期化時にコンストラクタに値を渡さないかもしれない。上記の例では必ず
(make-something #f #f #f)
なんて書かないといけないが、protocolを定義すると事情が変わってくる。
(define-record-type something
  (fields (mutable f1)
          (mutable f2)
          (mutable f3))
  (protocol (lambda (p)
              (lambda args
                (let-optionals* args ((f1 #f)
                                      (f2 #f)
                                      (f3 #f))
                  (p f1 f2 f3))))))
let-optionals*は探せばいろいろあると思うけど、Sagittariusでは(sagittarius control)ライブラリで提供。こうすると上記のmake-somethingがこんな風に書ける
(make-something 'value)
ここまでは、まぁ割と当たり前なんだけど、Sagittariusの一つの特徴としてキーワードを認識する。っで、キーワードを使ってこんな風に書ける。
#!compatible ;; キーワードはr6rsモードでは動かない
(import (rnrs)
        (sagittarius control)) ;; let-keywords let-keywords*もこの中
(define-record-type something
  (fields (mutable f1)
          (mutable f2)
          (mutable f3))
  (protocol (lambda (p)
              (lambda args
                (let-keywords args ((f1 #f)
                                    (f2 #f)
                                    (f3 #f))
                  (p f1 f2 f3))))))

(make-something :f3 'value)
let-keywordsはGaucheからもらってます。これが地味に便利。フィールドが少ないうちはそんなに感じないけど、10個くらいあって、7番目だけ値を入れたいなんて場合にこれが活躍してくる。難点は、全部に値を設定したい場合に一々キーワードを書かないといけないところか。ま、トレードオフだろう。

No comments:

Post a Comment