本章で述べる機能は (rnrs r5rs (6)) ライブラリで公開され、本報告書の先の版 [8] の機能で、現在の報告書では本体部分から省略されたもののいくつかを提供している。
(exact->inexact z) procedure (inexact->exact z) procedure
これらは inexact、 exact 手続きと同じである。R6RS:翻訳:R6RS:11.7 Arithmeticの「総称的な変換」を参照。
これらの手続きは数値理論的な(整数の)除算を実装する。 n2 は 0 であってはならない。これらの手続きはすべて整数オブジェクトを返す。 n1/n2 が整数オブジェクトであるとき、
(quotient n1 n2) ⇒ n1/n2 (remainder n1 n2) ⇒ 0 (modulo n1 n2) ⇒ 0
n1/n2 が整数オブジェクトでないとき、
(quotient n1 n2) ⇒ nq (remainder n1 n2) ⇒ nr (modulo n1 n2) ⇒ nm
ここで、nq は n1/n2 を 0 に向かって丸めたもので、 0 < |nr| < |n2| で 0 |nm| < |n2|、 nr と nm は n2 の倍数により n1 と異なり、 nr は n1 と同じ符号をしてい、 nm は n2 と同じ符号をしている。
したがって、整数オブジェクト n1 と n2 について、n2 が 0 でないとき、
(= n1 (+ (* n2 (quotient n1 n2)) (remainder n1 n2))) ⇒ #t
この計算に関連する数値オブジェクトはすべて正確である。
(modulo 13 4) ⇒ 1 (remainder 13 4) ⇒ 1 (modulo -13 4) ⇒ 3 (remainder -13 4) ⇒ -1 (modulo 13 -4) ⇒ -3 (remainder 13 -4) ⇒ 1 (modulo -13 -4) ⇒ -1 (remainder -13 -4) ⇒ -1 (remainder -13 -4.0) ⇒ -1.0
注: これらの手続きは div と mod (R6RS:翻訳:R6RS:11.7 Arithmeticの「算術演算」参照)を使って以下のように定義することができる(引き数の型の確認は省略している)。
(define (sign n) (cond ((negative? n) -1) ((positive? n) 1) (else 0))) (define (quotient n1 n2) (* (sign n1) (sign n2) (div (abs n1) (abs n2)))) (define (remainder n1 n2) (* (sign n1) (mod (abs n1) (abs n2)))) (define (modulo n1 n2) (* (sign n2) (mod (* (sign n2) n1) (abs n2))))
delay は force 手続きとともに使って遅延評価や必要呼び出しを実装するのに使われる。 (delay <expression>) は、ある未来のある時点で(force 手続きによって) <expression> を評価し、結果値を取り出せる、プロミスと呼ばれるオブジェクトを返す。
promise はプロミスでなければならない。 force 手続きはプロミスの値を取り出す。 promise について何の値も計算されていない場合には値を計算し、それを返す。プロミスの値はキャッシュ(あるいは「メモ化」)され、2番目に force されたときには、以前に計算した値が返される。
(force (delay (+ 1 2))) ⇒ 3 (let ((p (delay (+ 1 2)))) (list (force p) (force p))) ⇒ (3 3) (define a-stream (letrec ((next (lambda (n) (cons n (delay (next (+ n 1))))))) (next 0))) (define head car) (define tail (lambda (stream) (force (cdr stream)))) (head (tail (tail a-stream))) ⇒ 2
プロミスは主に関数型で書かれたプログラムを意図している。以下の例ではよいプログラミングスタイルを示しているものとは考えられないが、何度 force してもプロミスひとつに対して値がひとつだけ計算されることを示している。
(define count 0) (define p (delay (begin (set! count (+ count 1)) (if (> count x) count (force p))))) (define x 5) p ⇒ a promise (force p) ⇒ 6 p ⇒ a promise, still (begin (set! x 10) (force p)) ⇒ 6
ここに、 delay と force の実装例を示す。ここではプロミスは無引き数の手続きとして実装されており、 force は単純にその引き数を呼び出している。 Here is a possible implementation of delay and force. Promises are implemented here as procedures of no arguments, and force simply calls its argument:
(define force (lambda (object) (object)))
式
(delay <expression>)
は手続き呼び出し
(make-promise (lambda () <expression>))
と同じ意味であり、以下のようにすることができる。 as follows
(define-syntax delay (syntax-rules () ((delay expression) (make-promise (lambda () expression))))),
ここで make-promise は次のように定義することができる。
(define make-promise (lambda (proc) (let ((result-ready? #f) (result #f)) (lambda () (if result-ready? result (let ((x (proc))) (if result-ready? result (begin (set! result-ready? #t) (set! result x) result))))))))
n は正確な整数オブジェクト 5 でなければならない。 null-environment 手続きは eval とともに使うのに適した環境指定子を返し、この指定子は前の版の報告書 [8] で述べられてえいたすべてのキーワードの(構文)束縛と、 (rnrs base (6))と同様に =>、 ...、 else、 _ だけを含んでいる。
n は正確な整数オブジェクト 5 でなければならない。 scheme-report-environment 手続きは、前の版の報告書 [8] で述べられていた識別子への束縛から、 load、 interaction-environment、 transcript-on、 transcript-off、 char-ready? を除いたものを含む環境指定子を返す。変数の束縛は値としては本報告書で述べられた同名の手続きと同じである。 =>、 ...、 else、 _ のキーワード束縛についても本報告書で述べたものと同じである。