Scheme の練習。x の n 乗を計算する power。

Scheme の練習として、xn 乗を計算する power を書いてみた。


あ、そうだ。一応言っときますけど、たいていの Scheme 処理系には、expt という手続きが用意されているはずなので、ここで示す power なんて手続きを用意する必要はないです。以下はあくまで練習のために書いたという話です。


で、これが書いてみたやつ:

(define (power x n)
    (if (= n 1)
        x
        (* x (power x (- n 1)))))


ただし、n には 1 か、1 より大きい整数を渡す事。じゃないと停止しない。

何も起こらない

これをコマンドラインから呼び出せるようにしたい。そこで、上記の内容を power という名前のファイルに書いて、実行許可フラグを立てたり、shebang 書いたり。

%cat power
#! /usr/local/bin/gosh

(define (power x n)
    (if (= n 1)
        x
        (* x (power x (- n 1)))))

%chmod +x power
%./power 2 3
%


何も起こらない。main という手続きが無いからだ。

main 手続きを書く

Gauche ユーザリファレンスの『3.3 Schemeスクリプトを書く』によると:

ファイルが正常にロードされたら、goshは userモジュールに `main' という手続きが定義されているかどうか調べ、定義されていればそれを呼びます。mainには、スクリプトへの引数のリストが唯一の引数として渡されます。リストの最初の要素はスクリプトファイル名です。


と書いてある。こういうことだな:



そこで、main 手続きを何とか書いてみた。

#! /usr/local/bin/gosh

(define (power x n)
    (if (= n 1)
        x
        (* x (power x (- n 1)))))

(define (main args)
    (display (power (string->number (car (cdr args)))
        (string->number (car (cdr (cdr args))))))
    (display "\n"))


power を、2 つの引数を与えて呼び出したいだけなのに、なんだかすごいことになってる。


でも、とりあえず動きます。

%./power 2 3
8
%

cadr caddr

すごい事になっちゃってる carcdr の嵐をなんとかする:

(define (main args)
    (display (power (string->number (cadr args)) (string->number (caddr args))))
    (display "\n"))


少しは読みやすくなったかな。


(car (cdr x))(cadr x) と書ける。(car (cdr (cdr x)))(caddr x) と書いても同じこと。

first second third

リスト操作ライブラリの SRFI-1 を使って、もうちょっと:

#! /usr/local/bin/gosh
(use srfi-1)
(define (power x n)
    (if (= n 1)
        x
        (* x (power x (- n 1)))))

(define (main args)
    (display (power (string->number (second args)) (string->number (third args))))
    (display "\n"))


(use srfi-1) とすることによって、ライブラリを読み込んだので、second とか third が使えるようになった。


ちなみに、この場合 (first args) は、スクリプトの名前を返します。


2 の 100 乗。

%./power 2 100
1267650600228229401496703205376
%echo '2^100' | bc
1267650600228229401496703205376


あってる。

参考文献

Gauche ユーザリファレンス
http://practical-scheme.net/gauche/man/gauche-refj.html
Manpage of bc
http://www.linux.or.jp/JM/html/GNU_bc/man1/bc.1.html
carはカー、cdrはクダー、ではcadrやcaddrは? - *「ふっかつのじゅもんがちがいます。」withぬこ
http://d.hatena.ne.jp/ajiyoshi/20080902/1220350887