補足:代入による効果と履歴状態 プログラミング論 I 代入による効果のための set!式 今までの「単一代入則」の世界 • 一度定義した変数の値は変わることはなかった • よって関数が、外部で定義された値を参照しても文脈独 立であった (同じ引数なら同じ結果を返す) 変数の値を「更新」する set!式 :記憶(状態)を扱うのに 有用(注意 - 変数の値はタイミングにより異なる可能性) set!式: (set! 変数 式) - 式の結果を変数の値とする - 通常のscheme式のような結 果値はなく効果だけ(代入) (注:DrSchemeはAdvanced Studentの設定に) > (define v 1) > v 1 > (define v (+ v 1)) cannot redefine name: v > (set! v (+ v 1)) > v 2 (define (avg alon) (local ((define C 0) (define (avg-a alon accum) (cond [(empty? alon) (/ accum C)] [else (begin (set! C (+ C 1)) (avg-a (rest alon) (+ accum (first alon))))]))) (avg-a alon 0))) ;;(avg (list 1 3 5)) -> 3 効果に順序をつける begin式 set!式 は記憶(状態)を扱うのに有用な反面、変数の値 はタイミングにより異なる可能性がある ⇒ 値の変更の順序を制御するには begin 式を使う (begin 式1 … 式n 式) • キーワード begin と、引き続く n+1個の式の連続から成る。 • 式を順番に評価し最後の式の値が begin式全体の値。 • 次の結果は15 (define x 3) (define y 3) (begin (set! x (+ x 2)) (* x y)) • 参考:手続き型言語(後期のC言語など) 例題 関数sumの accumulator-style 化 第10回例題2のaccumulator-styleの関数sum ;; sum : (listof number) -> number ;; to compute the sum of the numbers on alon0 (define (sum alon0) (local (;; accum is the sum of the numbers that ;; preceded those in alon on alon0 (define (sum-a alon accum) (cond [(empty? alon) accum] [else (sum-a (rest alon) (+ (first alon) accum))]))) (sum-a alon0 0))) 例題 関数sumの accumulator-style 化 set!式および begin 式を使うことで履歴を引数として渡 さずとも変数の更新で履歴を使った関数sumを定義できる ;; sum : (listof number) -> number ;; to compute the sum of the numbers on alon0 (define (sum alon0) (local (;; accum is the sum of the numbers that ;; preceded those in alon on alon0 (define accum 0) accumulator 用の変 数を局所的に定義 (define (sum-a alon) (cond accumulator 用の変数は引数で渡さない [(empty? alon) accum] [else (begin (set! accum set!式で accumulator (+ (first alon) accum))) 用の変数を更新する (sum-a (rest alon)))]))) (sum-a alon0))) 練習 set!式 および begin 式 1. 以下の計算の結果を求めよ i) (define x 1) (define y 1) (begin (set! x (+ x 1)) (set! y (- y 1)) (* x y)) ii) (define x 3) (define y 5) (begin (set! x y) (set! y x) (list x y)) 2. 階乗を求める構造再帰関数を、 set!式および begin 式を使い、変数の更新で履歴を処理する関数にせよ。 ;; ! : N -> N ;; to compute n * (n-1) * ... * 2 * 1 (define (! n) (cond [(zero? n) 1] [else (* n (! (sub1 n)))]))
© Copyright 2024 ExpyDoc