関数内で局所変数を使いたいときには let を使って定義できる。
let 式は、(let binds body) という形をしている。具体例を示そう。
gosh> (let ((x 2) (y 3)) (* x y)) 6
これを使って同ページにある練習問題をやってみよう。
練習問題 1
Scheme 入門 4 の練習問題を1つの関数で書いてみてください。
つまり、初速度 v, 角度 a 度で投げたボールの飛ぶ距離を求める関数を書いてください。
おっと、その前に入門4の練習問題を示しておかないと。
練習問題 2
ボールを投げたときに飛ぶ距離を求める関数を以下の手順で書いてみようと思います。
- 角度の度を弧度法単位(ラジアン)に変換する関数。
180 度は π ラジアンである。 π の定義は、
(define pi (* 4 (atan 1.0)))
を用いよ。- 速度 vx で等速運動するものが t 秒間に移動する距離を求める関数。
- 垂直方向の初速度 vy で投げたものが落ちてくるまでの時間を 計算する関数。
空気抵抗は無視し、重力加速度 g は 9.8 m s-2 とする。
ヒント:落ちてくるときの速度は -vy になっているから、
2 vy = g t
が成り立つ。ここで t は落ちてくるのにかかる時間である。- 1–3 の関数を利用して、初速度 v で角度 theta 度で投げたものが飛ぶ距離を求める関数。
ヒント:まず、最初に関数を利用して角度 theta を弧度法単位に換算する(それを theta1 とする)。
垂直、水平方向の初速度はそれぞれ v sin(theta1), v cos(theta1) で表される。 落ちてくるまでにかかる時間は関数3を用いて計算できる。 水平方向に加速度はかからないので、飛ぶ距離は関数2を用いて計算できる。- 初速度 40 m/s, 角度 30 度で投げたボールが飛ぶ距離を上で定義した関数を用いて求めよ。 (肩の強いプロ野球選手が遠投したときの距離に近い値になります。)
この練習問題2の回答はこうなる。
(define pi (* 4 (atan 1.0))) (define deg->rad (lambda (deg) (/ (* deg pi) 180.0))) (define distance (lambda (vx t) (* vx t))) (define vtime (lambda (vy) (/ (* 2 vy) 9.8))) (define throw (lambda (v theta) (distance (* v (cos (deg->rad theta))) (vtime (* v (sin (deg->rad theta))))))) (print (throw 40.0 30.0))
実行:
^o^ > gosh throw.scm 141.39190265868385
で、こっちが let の練習問題の回答。度で与えられた角度をラジアンに変換して局所変数 r に束縛している。
(define throw (lambda (v a) (let ((r (/ (* a 4 (atan 1.0)) 180.0))) (/ (* v (cos r) 2 v (sin r)) 9.8)))) (print (throw 40.0 30.0))
実行:
^o^ > gosh throw2.scm 141.39190265868385