■Scheme(gouche)を使ってみる。
$ sudo apt-get install -y gauche gauche-doc
$ dpkg -l | awk '$1 ~ /^ii/&&$2 ~ /^gauche/{gsub(" *",",",$0);print $0}'
ii,gauche,0.9.5-1,amd64,Scheme script engine
■マニュアルは日本語版がローカルで見れる。
$ info gauche-refj.info
■Hello World
displayに直接渡すと、「#<undef>」が出たり「\n」を入れないといけなかったりするし、
printでも「#<undef>」が出るので、
そのまま評価するか、「x->string」を使う。
$ echo '"Gauche"'| gosh -i | sed -e 's/gosh> //g'
"Gauche"
$ echo '(x->string "Hello, World")' | gosh -i | sed -e 's/gosh> //g'
"Hello, World"
■1~nの総和の計算
$ echo '(define (fact n)
(cond ((= n 0) 0)
((= n 1) 1)
(else(+ n (fact (- n 1)))) ))
(fact 100)
' | gosh -i | sed -e 's/gosh> //g'
fac
5050
■seqと同様の動きをするiotaで書いてみる。
$ echo "(+ $(seq 1 100))" | gosh -i | sed -e 's/gosh> //g'5050
$ echo '(define (fact n)(fold + 0 (iota n 1)))(fact 100)' | gosh -i | sed -e 's/gosh> //g'
fact
5050
■goshのデバッグはtraceだけでは足りないので、以下のようにする。
condはif文を重ねた動作をする。
(use slib)(require \047trace)(trace fact)
$ echo -e '(define (fact n)
(cond ((= n 0) 0)
((= n 1) 1)
(else(+ n (fact (- n 1)))) ))
(use slib)(require \047trace)(trace fact)(fact 100)
' | gosh -i | sed -e 's/gosh> //g'
fact
CALL fact 100
CALL fact 99
CALL fact 98
CALL fact 97
CALL fact 96
RETN fact 4656
RETN fact 4753
RETN fact 4851
RETN fact 4950
RETN fact 5050
5050
■ガウスの和算
$ echo "(+ (* 100 50) 50)" | gosh -i | sed -e 's/gosh> //g'
5050
$ echo '(define (fact n)
(/ (* (+ n 1) n) 2))
(fact 100)
' | gosh -i | sed -e 's/gosh> //g'
fact
5050
■階乗
$ echo -e '(define (fact n)
(cond ((= n 0) 0)
((= n 1) 1)
(else(* n (fact (- n 1)))) ))
(use slib)(require \047trace)(trace fact)(fact 10)
' | gosh -i | sed -e 's/gosh> //g'
fact
CALL fact 10
CALL fact 9
CALL fact 8
CALL fact 7
CALL fact 6
RETN fact 720
RETN fact 5040
RETN fact 40320
RETN fact 362880
RETN fact 3628800
3628800
■フィボナッチ数列
ものすごく非効率的なので、2桁を超える大きな数は扱わない方が良い。
$ echo '(define (fib n)
(cond ((= n 0) 0)
((= n 1) 1)
(else (+ (fib (- n 1)) (fib (- n 2)))) ))
(map fib (iota 31))' | gosh -i | sed -e 's/gosh> //g'
fib
(0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 2584 4181 6765 10946 17711 28657 46368 75025 121393 196418 317811 514229 832040)
$ echo '(define (fib n)
(cond ((= n 0) 0)
((= n 1) 1)
(else (+ (fib (- n 1)) (fib (- n 2)))) ))
(map fib (iota 31))' | gosh -i | sed -e 's/gosh> //g' -e '/fib/d' -e 's/(\|)//g' -e 's/ /\n/g' | nl -v 0
0 0
1 1
2 1
3 2
4 3
5 5
6 8
7 13
8 21
9 34
10 55
11 89
12 144
13 233
14 377
15 610
16 987
17 1597
18 2584
19 4181
20 6765
21 10946
22 17711
23 28657
24 46368
25 75025
26 121393
27 196418
28 317811
29 514229
30 832040
■ネイピア数
$ echo "(exp 1)" | gosh -i | sed -e 's/gosh> //g'
2.718281828459045
■tan(e)
$ echo "(tan (exp 1))" | gosh -i | sed -e 's/gosh> //g'
-0.4505495340698077
■πの計算
三角関数の逆関数で円周率 clisp
https://labunix.hatenadiary.org/entry/20120101
atan 1 = π/4、acos(-1) = π、asin(1) = π/2
■アークタンジェントによる円周率の計算
$ echo "(* 4 (atan 1))" | gosh -i | sed -e 's/gosh> //g'
3.141592653589793
■アークコサインによる円周率の計算
$ echo "(acos -1)" | gosh -i | sed -e 's/gosh> //g'
3.141592653589793
■アークサインによる円周率の計算
$ echo "(* -2 (asin -1))" | gosh -i | sed -e 's/gosh> //g'
3.141592653589793
■πを使った計算
goshの起動時に読み込ませる際に関数から変数に変換してみる。
個人的にはatanを使った公式の方が好みなのだけど、今回はacosで。
$ cat pi.scm
(define (func-pi) (acos -1))
(define pi (func-pi))
$ gosh -l ./pi.scm
gosh> pi
3.141592653589793
gosh> (/ pi 2)
1.5707963267948966
gosh> (exit)
$ echo '(/ pi 2)' | gosh -i -l ./pi.scm | sed -e 's/gosh> //g'
1.5707963267948966
■上記が出来るなら直接変数にすれば良いということで。
$ cat pi2.scm
(define pi (acos -1))
$ echo '(/ pi 2)' | gosh -i -l ./pi2.scm | sed -e 's/gosh> //g'
1.5707963267948966
$ echo '(/ (* (* pi pi)) 6)' | gosh -i -l ./pi2.scm | sed -e 's/gosh> //g'
1.6449340668482264
■円周の計算
$ echo '(* 2 pi 1)' | gosh -i -l ./pi2.scm | sed -e 's/gosh> //g'
6.283185307179586
■組み込みのlogを使う。
$ echo "(log 2)" | gosh -i | sed -e 's/gosh> //g'
0.6931471805599453