PowerPoint プレゼンテーション

補足:代入による効果と履歴状態
プログラミング論 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)))]))