[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
[R5RS] 各変数varがexprの値に束縛されているローカルな環境を作成し、 その中でbody …を評価します。varはシンボルでなければ ならず、重複があってはなりません。body …の最後の式の値が このフォームの値となります。
これらの3つのフォームの違いは、exprが評価される時点のスコープにあります。
let
はexprをletフォームに入る前の環境において評価します。
let*
はexprを順に、それ以前のvarが束縛された環境において評価して
ゆきます。letrecは全てのvarが仮想的に不定の値に束縛された環境において
各exprを評価します。letrecは相互再帰的なローカル関数を定義する場合に
必要です。
(define x 'top-x) (let ((x 3) (y x)) (cons x y)) ⇒ (3 . top-x) (let* ((x 3) (y x)) (cons x y)) ⇒ (3 . 3) (let ((cons (lambda (a b) (+ a b))) (list (lambda (a b) (cons a (cons b 0))))) (list 1 2)) ⇒ (1 2 . 0) (letrec ((cons (lambda (a b) (+ a b))) (list (lambda (a b) (cons a (cons b 0))))) (list 1 2)) ⇒ 3 |
変数が一つしか無い場合の便利なマクロです。次のように展開されます。
(let ((var expr)) body …) |
このマクロは次のようなイディオムを簡素化します。
(let1 var expr (if var then else)) |
このマクロは次のようなイディオムを簡素化します。
(let1 var expr body … var) |
[SRFI-2]
簡単に言うと、このフォームはlet*
のように動作しますが、
bindings中の式が#f
に評価されたらそこで評価を打ち切り
#f
を返します。
各bindingは以下のいずれかの形式でなければなりません。
expressionが評価されます。それが真の値を返したら、その値がvariable
に束縛され、次のbindingへと進みます。もうbindingが無ければ
body …が評価されます。もしexpressionが#f
を返したら、
評価を打ち切り、and-let*
から#f
を返します。
この形式ではvariableが省略されています。Expressionが評価され、 その結果は評価を続行するか打ち切るかを判断するためにのみ使われます。
この形式ではbound-variableは束縛変数を示す識別子でなければなりません。 その変数の値が偽でなければ評価を続行します。
いくつか例を挙げます。次のコードは連想リストalistからkeyを 探し、見つかったらその値を返します。
(and-let* ((entry (assoc key alist))) (cdr entry)) |
もしargが正確な整数の文字列表現だった場合はnumを返し、そうでなければ 0を返します:
(or (and-let* ((num (string->number arg)) ( (exact? num) ) ( (integer? num) )) num) 0) |
以下のコードはとあるサーバーのポート番号をいくつかの可能性 (環境変数、設定ファイル…)の中から探す仮想的なコードです。
(or (and-let* ((val (sys-getenv "SERVER_PORT"))) (string->number val)) (and-let* ((portfile (expand-path "~/.server_port")) ( (file-exists? portfile) ) (val (call-with-input-string portfile port->string))) (string->number val)) 8080) ; default |
動的スコープの変数をエミュレートするマクロです。
varはfluid-let
フォームを含むスコープで定義されている
変数でなければなりません。valは式です。
fluid-let
はまずvalを評価し、
valをvarに動的スコープで束縛してbody … を評価します。
マルチスレッド環境下では、varの値の変化は全てのスレッドから見えます。
このフォームは主として他の処理系のコードを移植する際の利便性のために
追加されました。スレッドローカルな動的状態を実現するには、
パラメータオブジェクト(gauche.parameter
- パラメータ参照)を
使って下さい。
(define x 0) (define (print-x) (print x)) (fluid-let ((x 1)) (print-x)) ⇒ ;; prints 1 |
[SRFI-8] この構文により、多値を受け取ることができます。 formalsはシンボルのリストです。不完全なリストであっても構いません。 expressionが評価され、返された値がlambda形式の引数の束縛と 同じようにしてformals内の変数と束縛され、その環境下でbody …が 評価されます。
(define (divrem n m) (values (quotient n m) (remainder n m))) (receive (q r) (divrem 13 4) (list q r)) ⇒ (3 1) (receive all (divrem 13 4) all) ⇒ (3 1) (receive (q . rest) (divrem 13 4) (list q rest)) ⇒ (3 (1)) |
なお、多値のcall-with-values
は
receive
と等価な手続き的インタフェースです。
多値を複数のトップレベル変数に束縛するには、define-values
(定義参照) が使えます。
また、SRFI-11 (srfi-11
- Let-values) のlet-values
と
let*-values
はlet
のような形式で多値を扱うことができます。
[SRFI-31] 再帰的な参照のある式の評価を行うマクロです。
最初の形式は、varがexprの結果に束縛される状態でexprを 評価します。 2番目の形式は以下の形式と等価です。
(rec name (lambda vars expr …)) |
例:
;; constant infinite stream (rec s (cons 1 (delay s))) ;; factorial function (rec (f n) (if (zero? n) 1 (* n (f (- n 1))))) |
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] |
This document was generated by Shiro Kawai on November, 22 2009 using texi2html 1.78.