Parenist養成ゼミ: 制御構造
この記事は、Parenist養成ゼミシリーズの記事である。
今回は、制御構造について理解し、反復処理や条件分岐等の制御構造を用いるとより抽象的なプログラムが記述できるようになることを理解することを目的とした。
制御構造
begin
special operator begin
は、複数の式を逐次評価し、最後に評価した結果を返す。
) (begin 0 1 2)
2
返り値は最後の式であるから、begin
の用途はその途中の式の副作用にある。
) (begin (write 0) (write 1) (write 2))
0
1
2
2
return
special operator return
は、一番近いfunction contextから脱出し、値を返す。
) (function double (x) (return 10) (* x 2))
double
) (double 10)
10
if
special operator if
は、条件によって評価する式を評価する。
(if TEST THEN
[TEST THEN] ...
[ELSE])
if
は先頭から順に2i
番目の式TEST
を評価する。評価した結果がnil
でなかった場合、直ちに2i + 1
番目のTHEN
式を評価した結果をif
の返り値として、2i + 1
番目以降の式の評価は行わない。
最後の2i + i
番目の式を省略することができ、この場合は、ELSE
式が評価されると、その結果がif
の返り値となる。
) (if true 1)
1
) (if nil 1)
nil
) (if true 1
2)
1
) (if nil 1
2)
2
) (if nil 1
nil 2
3)
3
if
の定義から、nil
以外のすべての値が真と見做される。そのため、真の代表元として、symbol true
がある。true
はnil
同様に、評価されると自身を返す。
) nil
nil
) true
true
loop, break, continue
special operator loop
は永遠に式を評価し続ける。
) (loop (write 1))
1
1
...
loop
のcontextを抜けるために、C likeな言語と同等のspecial operator break
とcontinue
が存在する。
) (loop (write 1) (break) (write 2))
1
nil
) (loop (write 1) (continue) (write 2))
1
1
...
primitiveではない制御構造
macroを用いるとprimitiveな制御構造から容易に新たな制御構造を作ることができる。実際、組み込みのいくつかはそのようになっている。
begin0
macro begin0
は、begin
同様に複数の式を評価するcontextを生成する。最初に評価した結果を返す点を除き、begin
と同一である。
) (begin (write 0) (write 1) (write 2))
0
1
2
0
while
macro while
は条件を満たす間繰り返し評価を行う。
) (let (i 0)
(while (< i 3)
(write i)
(<- i (++ i))))
0
1
2
nil
dotimes, dolist
macro dotimes
やdolist
は容易に使用できる反復を行うためのcontextを生成する。
) (dotimes (i 3) (write i))
0
1
2
nil
) (dolist (i (.. 3)) (write i))
0
1
2
nil
when
macro when
は条件に一致する場合に複数の式を逐次評価するcontextを生成する。
(when test expr1 expr2 ...)
<=> (if test (begin ...))
課題
以下のプログラムを作成せよ。必要に応じて付録の関数をマニュアルで調べ使用せよ。
- コマンドライン引数から数値を2つ受け取り、その最大公約数を求めるプログラム
gcd.p
を作成せよ。 - コマンドライン引数から任意の数の数値を受け取り、一番小さい数を出力するプログラム
min.p
を作成せよ。 - コマンドライン引数から任意の数の数値を受け取り、昇順になっているか判定するプログラム
sorted.p
を作成せよ。 - 1から100までの値を表示するプログラム
fizz-buzz
を作成せよ。ただし、3の倍数はfizz、5の倍数はbuzz、3と5の両方の倍数はfizzbuzzと表示すること。 - 九九の表を出力するプログラム
multable
を作成せよ。ただし、実行例のように数値の列がalignされている必要はない。 - 実行例を参考に標準出力に文字列を出力するプログラム
zig-zag
を作成せよ。
実行例
$ paren gcd 20 30
10
$ paren min 30 10 20 40
10
$ paren sorted 30 10 20 40
nil
$ paren sorted 10 20 30 40
true
$ paren fizz-buzz
1
2
fizz
4
buzz
fizz
7
8
fizz
buzz
11
fizz
13
14
fizzbuzz
16
...
$ paren multable
1 2 3 4 5 6 7 8 9
2 4 6 8 10 12 14 16 18
3 6 9 12 15 18 21 24 27
4 8 12 16 20 24 28 32 36
5 10 15 20 25 30 35 40 45
6 12 18 24 30 36 42 48 54
7 14 21 28 35 42 49 56 63
8 16 24 32 40 48 56 64 72
9 18 27 36 45 54 63 72 81
$ paren fizz-buzz
1
2
fizz
4
buzz
fizz
7
8
fizz
buzz
11
fizz
13
14
fizzbuzz
16
...
$ paren zig-zag
*****
*****
*****
*****
*****
*****
*****
*****
*****
*****
*****
*****
*****
*****
*****
*****
*****
*****
*****
*****
*****
*****
...
付録
組み込み関数
必要に応じて以下のマニュアルを参照せよ。
入出力
read-line
-- 一行読み込みwrite-line
-- 一行書き出し
四則演算
+
-- 和-
-- 差*
-- 積/
-- 商%
-- 剰余
比較演算子
-
=
-
<
-
>
-
<=
-
>=
-
論理演算子
!
-- logical NOT&&
-- logical AND||
-- logical OR
文字列
int
-- 文字列から数値へ変換str
-- 数値から文字列へ変換、文字列の結合