For Gauche 0.9.10


Next: , Previous: , Up: 組み込みライブラリ   [Contents][Index]

6.16 パラメータ

「パラメータ」はSchemeで動的スコープを持つ状態を実現します。 Gaucheではスレッドローカルな状態の格納にも使えます。 もともとsrfi-39で仕様が定められ、R7RSからは言語の一部になりました。

parameterizeマクロはletに構文的に似ていて、 本体の実行の間、パラメータの値を一時的に置き換えます。 これは字句的(静的スコープ)ではなく動的スコープで動作します。

(define var (make-parameter 0))

(define (show-var) (print (var)))

(show-var)  ; prints 0

(parameterize ((var 1))
  (show-var))    ; prints 1


(define f)

(parameterize ((var 2))
  (set! f (lambda () (show-var))))

(f) ; prints 0, since its out of the dynamic extent of var=2

継続などにより制御がparameterizeの本体から飛び出したり本体へ飛び込んだり した場合、パラメータは常にそれがアクセスされる動的環境のもとでの値を返します。

GaucheはR7RSのパラメータを次のとおり拡張しています。

Function: make-parameter value :optional filter

[R7RS base] 初期値がvalueであるパラメータを作成します。 もし省略可能な引数filterが与えられた場合、 それは一つの引数を取る手続きでなければなりません。 パラメータの値が変更されようとした時、filterは与えられた値を 引数として呼ばれ、filterが返した値がパラメータの新しい値と なります。filterはエラーを報告したりパラメータの値を変えずに置くことも 可能です。

註: 0.9.9までは、この手続きはパラメータオブジェクトを返していました。 パラメータオブジェクトは object-applyメソッドによって手続きであるかのように 振る舞います。しかし、R7RSはmake-parameterが手続きを返すように 規定しており、ポータブルなコードでは (procedure? (make-parameter 'z))#tでなければなりません。

0.9.10から、make-procedureは手続きを返すようになりました。 通常のパラメータの使い方をしている限り、外部に見える振る舞いは変わりません。 ただし、make-parameterで作られたオブジェクトかどうかを (is-a? p <parameter>)でテストしているコードは 後述するparameter?を使うように変更する必要があります。

Macro: parameterize ((param value) …) body …

[R7RS base] body …を評価します。 但し、body … の実行中のみ、パラメータparamの値を valueに変更します。最後のbodyの返した値を返します。

例:

(define a (make-parameter 1))
(a) ⇒ 1
(a 2) ⇒ 1
(a) ⇒ 2
(parameterize ((a 3))
  (a)) ⇒ 3
(a) ⇒ 2
Function: parameter? obj

objmake-parameterで作られたものであった場合は#tを、 そうでなければ#fを返します。

註: 組み込みの手続きの中には、パラメータのように動作するものがあります (例: current-input-port)。しかしそれらは、make-parameterで 作られたものでない限り、parameter?に対して#fを返します。


Next: , Previous: , Up: 組み込みライブラリ   [Contents][Index]