向日葵でた!

向日葵。小さいからわからないかな

遠い昔に雑誌に載っていたフィボナッチ数列で向日葵の種の配置を出すプログラムをHaskellに置き換えてみた。原典はN88Basicで書かれていたけど、気に入っていてCやSmartEiffel、Javaに置き換えていたもの。今回は関数型言語ということで結構躓いた。
まずはループの表現がわからなかった。for(i=0;i<10; i++) {}を何に置き換えるのか。文献には、リストで置き換えると書いているけどその意味がぴんとこなくて苦労した。
ループひとつについて、以下の感じになる(ほかにも表現方法はたくさんある、これは一例)

{-
   リストから、最初の要素を取り出して、sub21を実行。
   次の要素移行はリストとして、自分自身に渡す。(右側再帰とか言うやつ)
-}
sub20 (x:xs) = sub21 n : sub20 xs
sub20 [] = []

sub21 n = do
    -- ここで処理を書く

main = do
    -- 呼び出しはこんな感じ
    sub20 [1..10]

このあたりの表現については、http://www.haskell.org/~pairwise/intro/intro.htmlにCプログラマのためのHaskell入門として解説がある。

書いてみると、本体と繰り返し構造が分離してすっきりする。そういえば、数学ではこんな表現だったなぁと改めて文献で書いていることに納得。

次に詰まったのは、OpenGLでの頂点情報の入れ方。これも同じサイトにhttp://www.haskell.org/~pairwise/HOpenGL/HOpenGL.htmlがあり、記述するための参考になった。説明はテクスチャーを使っているけど、不要なのでそこをはずして利用した。

あとは、関数を定義しているけど、戻り値の型が違ったときどうすればいいのかよくわからない。
これは、副作用を当てにしている手続き型に慣れているせいかなぁ。遅延評価だから。適当に変数にセットしただけでは評価されないし、このあたりは慣れなんだろうなぁ。

ということで何とか動作するところまできた。


このプログラムって、昔、初めて打ち込んで実行したときに、下から、少しずつ種(球面上の小さい円−傾いているから楕円に見える)がぱらぱら、ぱらぱらと数分かかって出ていたのよね。

今では一瞬。技術の進歩を感じますねぇ。(ハード価格は・・・下がっているなぁ)
今回は、速度比較とかまでできそうにないけど、数式をそのまま記述できる感じで書けるところは強みですねぇ。


手続き型言語から関数型言語にはいるにあたっての先の「CプログラマのためのHaskell入門」みたいな感じの解説書があればとてもうれしい。今出ている2冊も参考にはなるけど、ファイル処理を中心に解説されていて、手続き型プログラムに慣れている人から移行(もしくはつまみ食い)するには、ちょっとつらい気がする。読んでいるときにはなるほどって思っていたけど、実際に書いてみると、ループだとか、変換だとかいったところで苦労したなぁ。


P.S
書棚、探していたら、原典があった。
原典 東川 和夫 「ひまわりのたね」「数学セミナー」 1985年07月号 pp.34-42
図15 「球面上にたねがついたら」で紹介されているBASICのプログラム
20年以上前だったのねぇ。この頃だと、FM8か11だろうなぁ。懐かしいねぇ