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-- 数値から文字列へ変換、文字列の結合