最近の更新 (Recent Changes)

2014-01-01
2013-01-04
2012-12-22
2012-12-15
2012-12-09

Wikiガイド(Guide)

サイドバー (Side Bar)

--
← 前のページに戻る

2. Closure Basicのプログラム例

まずは、Closure Basicのプログラム例を見てもらい、雰囲気を味わっていただきましょう。 詳しい文法の仕様については、後の項で説明します。

関数・サブルーチン以外は、特別な文法はないので見ただけでほとんど理解できることでしょう。

a. forループ

まず、for文によるループ処理です。

Basic言語のfor, nextと同様の記述ができます。


for i=0 to 10
        for j = 0 to 10
                print i,j
        next
next

変数は定義しなくても、プログラム上で現れたときから、値を代入してそのまま使えます。

上では、変数i, jに数字を入れて2重ループを実行して、その値を表示します。

このプログラムは、デカルト言語のパッケージの中の"example/ClosureBasic/test/for2.cbs"にあります。 このページで紹介するプログラム例は、デカルト言語のパッケージの中の"example/ClosureBasic/test/"にあるので探してみてください。

実行結果を以下に示しましょう。


$ descartes ClosureBasic for2.cbs
Compiling...
Run
0 0
0 1
0 2
0 3
0 4
0 5
0 6
0 7
0 8
0 9
0 10
1 0
1 1
1 2

  ...途中略

9 8
9 9
9 10
10 0
10 1
10 2
10 3
10 4
10 5
10 6
10 7
10 8
10 9
10 10
result --
        <compile_run>
-- true

b. 配列

配列は、変数ですが特別扱いであり、その大きさを事前に定義しておかなければなりません。

dimを使って定義します。これもBasicから構文を借りています。

dim2.cbsを以下のようにします。


dim dt[10]
dim dt2[10]

for i = 0 to 10
        dt[i] = i
        print i, dt[i]
next

print dt[0]
print dt[9]
print dt[10]

for i = 0 to 10
        dt2[i] = i
        print i, dt2[i]
next

print dt[10]

print "--"

for i = 0 to 10
        print dt[i]
next

実行結果を以下に示しましょう。


$ descartes ClosureBasic dim2.cbs
Compiling...
Run
0 0
1 1
2 2
3 3
4 4
5 5
6 6
7 7
8 8
9 9
10 10
0
9
10
0 0
1 1
2 2
3 3
4 4
5 5
6 6
7 7
8 8
9 9
10 10
10
--
0
1
2
3
4
5
6
7
8
9
10
result --
        <compile_run>
-- true

c. 階乗

リカーシブ(再帰的)な関数を書いてみましょう。 階乗を計算する関数を定義します。

関数は{fun(引数) 処理本体}の形式の無名関数(かつクロージャ)として定義して、それを変数に代入すると名前付きの関数になります。

変数には決まった型がなく、数、文字列に加えて、関数(クロージャ)を自由に代入することができます。

これは、Basicにはない構文ですね。

factor.cbsを以下のようにします。



fact = {fun (n)
        if n <= 1 then
                return 1
        else
                return n*fact(n-1)
        end
}

print fact(3)
print fact(5)
print fact(8)

実行結果を以下に示しましょう。


$ descartes ClosureBasic factor.cbs
Compiling...
Run
6
120
40320
result --
        <compile_run>
-- true

d. カウンター

クロージャを使ったカウンターのプログラムです。

counter変数に関数のクロージャを代入しています。 このクロージャーの中では、カウンターの値を保持する変数Cをローカル変数として持ちます。

また、counter関数(クロージャ)の内部関数として、以下のようなカウンター値を操作する関数を定義しています。

- カウンター値を表示するpr()

- カウンター値を+1するinc()

- カウンター値を-1するdel()

- カウンター値に値を設定するset(n)

これらの関数内関数(クロージャ内クロージャ)のpr, inc, del, setの変数にプログラムの最初で0を入れているのに着目してください。 なぜ、このようなことをしているかというと、これらの定義をcounter関数の外で行っていないと、 pr, inc, del, setがcounter関数はローカル変数となってしまいcounter関数の外部からアクセスできなくなるためです。 最初にグローバルな変数として定義しておいて、counter関数内で関数として定義することにより、counter関数のローカル変数にアクセスできるオブジェクト指向のメソッド関数のように定義できるのです。

なお、関数は必ず値を返すのですが、その関数の返り値を使わないでサブルーチンのように呼び出すには、callを使います。

counter.cbsを以下のようにします。


pr  = 0
inc = 0
dec = 0
set = 0

counter = { fun()
        c = 0

        pr = {fun () print c:return c}

        inc = {fun () c = c + 1: call pr(): return c}

        dec = {fun ()
                c = c - 1
                call pr()
                return c
        }

        set = {fun(n)
                c = n
                call pr()
                return c
        }

        return 0
}


print "call counter()"
call counter()

print "call pr()"
call pr()

print "call inc()"
call inc()

print "call inc()"
call inc()

print "call inc()"
call inc()

print "call dec()"
call dec()


print "call counter()"
call counter()

print "call pr()"
call pr()

print "call inc()"
call inc()

print "call set(7)"
call set(7)

print "call inc()"
call inc()

実行結果を以下に示しましょう。


$ descartes ClosureBasic counter.cbs
Compiling...
Run
call counter()
call pr()
0
call inc()
1
call inc()
2
call inc()
3
call del()
2
call counter()
call pr()
0
call inc()
1
call set(7)
7
call inc()
8
result --
        <compile_run>
-- true

e. Y コンビネーター

Closure Basicの無名関数はまさにλ関数の形をしています。 これを使って、Y コンビネーターを実現してみましょう。

Yコンビネータ(Y Combinator)とは何でしょうか。 簡単に言い切ってしまうと、無名関数だけで再帰プログラムに相当する処理を可能にするものです。

ここでは詳しくは述べませんが、WWW上でもいろいろと書いて解説してあるのが検索すると見つかるので調べてみてください。

まず、ソースです。このソース内では、Yコンビネータを使って、階乗とフィボナッチ数の計算を行っています。


' Y combinator
'

Y =
{fun(f)
	g = f
	return {fun(p) 
		q = p
		return g(
			{fun(a) return q(q) (a)}
		)
	}
	({fun(p) 
		q = p
		return g( 
			{fun(a) return q(q) (a)}
		)
	})
}


' factorial function

print "Factorial from 1 to 10"
print


fact = {fun(f)
	g=f
	return {fun(n)
		if n <= 1 then
			return 1
		else
			return n*g(n-1)
		end
	}
}

for i = 1 to 10
	print Y(fact)(i)
next

print "--"
print "Fibonacci number from 0 to 10"
print

' Fibonacci number

fib = {fun(f)
	g = f
	return {fun(n)
		if n = 0 then
			return 0
		else if n = 1 then
			return 1
		else 
			return g(n-1)+g(n-2)
		end
	}
}

for i = 0 to 10
	print Y(fib)(i)
next


y.cbsというファイル名で保存します。

実行結果を以下に示しましょう。


$ descartes ClosureBasic y.cbs
Compiling...
Run
Factorial from 1 to 10 is displayed.

1
2
6
24
120
720
5040
40320
362880
3.6288e+06
--
Fibonacci number from 0 to 10 is displayed.

0
1
1
2
3
5
8
13
21
34
55
result --
        <compile_run>
-- true