変数


Tags: R6RS, SRFI

トップレベルプログラムとライブラリボディーのトップレベルで定義した変数はそのプログラムおよびライブラリ内で参照・代入ができる。

(define *var* 1)

*var* ; => 1
(set! *var* 2)
*var* ; => 2

ただし、他のライブラリから import した変数に代入することはできず、他の言語で言うところの定数のようなものとして扱われる。

(library (some-library)
  (export *variable*)
  (import (rnrs))

  (define *variable* 1)
  )

(import (rnrs) (some-library))

(set! *variable* 2) ; => &assertion

また、リテラルとして書いたオブジェクト、 symbol->string により生成された文字列は変更が不可能なので注意が必要である。

(import (rnrs) (rnrs mutable-pairs) (rnrs mutable-strings))

(define xs '(1 2 3))
(define s1 "abc")
(define v '#(0 1 2))
(define s2 (symbol->string 'define))

(set-car! xs 0) ; => &assertion
(string-set! s1 0 #\d) ; => &assertion
(vector-set! v 2 3) ; => &assertion
(string-fill! s2 #\a) ; => &assertion

変更可能な大域的な状態を扱うには SRFI 39 のパラーメータオブジェクトを使う。パラメータオブジェクトの実体は make-parameter 手続きを使って生成されるクロージャであり、手続き呼び出しにより値を参照/設定する。

(import (rnrs) (srfi :39))

(define *x* (make-parameter 1))
(*x*) ; => 1
(*x* 2) ; => 2
(*x*) ; => 2
(library (some-library)
  (export var print-var)
  (import (rnrs) (srfi :39))

  (define var (make-parameter 1))
  (define (print-var)
    (display var))
  )

(import (rnrs) (some-library))

(print-var) ; -> 1
(var 3) ; => 3
(print-var) ; -> 3

パラメータの値を一時的に変更するには parameterize マクロを使う。

(define v (make-parameter 1))
(define (print-v)
  (display v))

(parameterize ((v 3))
  (print-v) ; -> 3
  )

(print-v) ; -> 1

このとき、 v の値は pameterize の本体部分の動的存続期間の間だけ値が 3 に変更される。