ocaml
図書館へは、10日と空けずに行っている。でも、たまには、オラの村さ来 てみんしゃいと お声がかかったので、出かけてみた。
そいたら、今週のお勧めだか、今月の旬だか知らないけれど、 入門 ClojureScriptなんてのを 紹介されたよ。 産地は、 Clojure to JS compilerって所らしい。 生産者は、clojureを作った、あの人のようだ。clojureを作っても、それを有効利用出来る ようにしないと、啼かず飛ばずになるからね。
clojureでJAVAを下敷きにしたんで、今度は世界で一番流行してるjavascriptに 打って出ようって訳。眼の付け所が違いますなあ。 今時、javascriptを素で使うなんておっくれてるーーって訳。まあ、javascriptを Web界のアセンブラーだとしたら、その上で、優雅にプログラムを書けるように してあげるのが、業界人の務めだろうよ。
日本にも賛同者が居て、ClojureScriptの導入 とか、 Clojure + ClojureScript 動かしてみたのでメモ 等が閲覧できるよ。
例によって、括弧まみれはイヤダって人は、rubyに似せて作られている Cofee-script等を試すがよかろう。この javascriptを見えなく(見なくてもよい)する試みは、世界各地で勃発してるから、いろいろ 見つかるであろうよ。
ocaml
とまあ、オラの村あたりを監視してると、世間の流行が分かるんだけど、数年前に流行って 今は流行遅れになったものがある。最近は、F#にも押されているしね。
こちらの方や、 あちらの方が、頑張っておられて 、海の向こうのオラの村では、Real World OCaml なんてのが、出たみたいですけど。いまいち、気勢が上がらないような気がします。
そこで、おいらも、F#の元祖、ocamlに再び手を出してみる事にします。
まずは、Ocaml関係のメタリンク あたりが良いですね。ここから辿れるOcaml.jpの中にあるマニュアル中の Pervasivesは、必読かな。
おいらが現在持ってるocaml関係の本と言うと、 プログラミングの基礎 ってやつが一冊だけ。ほかにらくだの絵が表紙になってたのもあったはずなんだけど、perlと 同様にフェードアウトしちゃったのかな。後は有名な、MinCamel ですかね。
Makefile
過去においらもocamlをやってた。古いアーカイブから資料を発掘してきたよ。 下記は、複数のファイルを合成してアプリを作る例。Webに載せておかないと離散 してしまいそう。
[sakae@pcbsd ~/Ocaml-sample/fact]$ cat main.ml open Fact;; let () = let n = Cv.cv Sys.argv.(1) in print_int ( f n ); print_newline();;
上記は、メインプログラム。型なしにして、引数はコマンドラインからやって来る。
[sakae@pcbsd ~/Ocaml-sample/fact]$ cat fact.ml let rec f n = if n = 0 then 1 else n * f (n - 1);;
言わずと知れたfactさん。
[sakae@pcbsd ~/Ocaml-sample/fact]$ cat cv.ml let cv s = int_of_string s
例の為の例。文字列を整数に変換。そして、下記はMakefile
[sakae@pcbsd ~/Ocaml-sample/fact]$ cat Makefile OCAMLC=ocamlc OCAMLOPT=ocamlopt OCAMLDEP=ocamldep INCLUDES=unix.cmxa str.cmxa # all relevant -I options here OCAMLOPTFLAGS=$(INCLUDES) # WARNING main.cmx(main.ml) must be last. PROG_OBJS=cv.cmx fact.cmx main.cmx myprog: $(PROG_OBJS) $(OCAMLOPT) -o myprog $(OCAMLOPTFLAGS) $(PROG_OBJS) strip myprog # Common rules .SUFFIXES: .ml .mli .cmo .cmi .cmx .ml.cmo: $(OCAMLC) $(OCAMLFLAGS) -c $< .mli.cmi: $(OCAMLC) $(OCAMLFLAGS) -c $< .ml.cmx: $(OCAMLOPT) $(OCAMLOPTFLAGS) -c $< # Clean up clean: rm -f myprog rm -f *.cm[iox] *.o # Dependencies (WARNING: touch .depend at first time, then make depend) depend: $(OCAMLDEP) -native $(INCLUDES) *.mli *.ml > .depend include .depend
実行例、最初に一度だけ、関係者を洗い出しておく。
[sakae@pcbsd ~/Ocaml-sample/fact]$ make depend ocamldep -native unix.cmxa str.cmxa *.mli *.ml > .depend [sakae@pcbsd ~/Ocaml-sample/fact]$ make ocamlopt unix.cmxa str.cmxa -c cv.ml ocamlopt unix.cmxa str.cmxa -c fact.ml ocamlopt unix.cmxa str.cmxa -c main.ml ocamlopt -o myprog unix.cmxa str.cmxa cv.cmx fact.cmx main.cmx strip myprog
いろいろと付属ファイルが出来ている。
[sakae@pcbsd ~/Ocaml-sample/fact]$ ls Makefile cv.ml fact.cmx main.cmi main.o cv.cmi cv.o fact.ml main.cmx myprog cv.cmx fact.cmi fact.o main.ml [sakae@pcbsd ~/Ocaml-sample/fact]$ ./myprog 5 120
こちらは、関係者
[sakae@pcbsd ~/Ocaml-sample/fact]$ cat .depend cv.cmo: cv.cmx: fact.cmo: fact.cmx: main.cmo: fact.cmx cv.cmx main.cmx: fact.cmx cv.cmx
OCaml備忘録 に詳しくファイルの役割が出ているので参照の事。
camlp4
ocamlは付属のcamlp4ってのを使うと、文法を拡張出来るらしい。
ocamlでは、リストの内包表記が出来ないけど、camlp4で出来るみたい。
# #load "dynlink.cma";; # #load "camlp4o.cma";; Camlp4 Parsing version 3.12.1 # #load "Camlp4Parsers/Camlp4ListComprehension.cmo";; # [x * x | x <- [1; 2; 3] ];; - : int list = [1; 4; 9]
camlp5系も有るみたい。普通に推測すると進化してんだなと思っちゃうけど、全っく 別物との事なので、注意しましょう。
F#からの輸入
F#がocamlを手本にして作られたのは知ってた。後発なので、ocamlに無い機能が 付けられている。最近、ocamlも4系になって、F#やhaskellから機能を取り込んで いるみたい。rubyがperlから、いろいろ取り込んでのは有名な話。その逆は? perlはもう、衰退モード突入したから、そんな元気は無いかも知れぬ。
パイプと関数合成。ocamlでやるには
let (|>) x f = f x let (<|) f x = f x let (>>) f g x = g (f x) let (<<) f g x = f (g x)
F#のパイプライン演算子・関数合成をOCamlで実装 が、詳しい。
原理は、演算子を前置するか、中置するかから来ている。
sakae@debian7:~$ ocaml Objective Caml version 3.12.1 # 3 + 5 ;; - : int = 8 # (+) 3 5 ;; - : int = 8
普通、プラス記号は、中置して上の例のように使われる。プラス記号を括弧でくくると 、関数のように前置して使える。こういう機能が提供されているので、演算子を関数と して、高階関数で扱えるようになるんだ。
# (*) 3 4 Warning 1: this is the start of a comment.
但し、掛け算記号の場合、括弧との間に隙間を設けないと、あらぬ勘違いをされる。
# ( *) 3 4;; Warning 2: this is not the end of a comment. - : int = 12 # ( * ) 3 4 ;; - : int = 12
コメント記号は、C語風にしておいてくれれば良かったのに。フランス人の考える事と言ったら、、、(以下自粛)
int vs. int32
ocamlの資料を読んでいると、普通の整数(int)は31Bitだそうだ。残りの1Bitは、内部的に 使っているんだな。多分、即値のフラグか何かだろう。で、問題になるのは、intが32Bit だと考えているアプリだと、MSBが桁落ちしてしまい大変な事になる。そこでフランス人は 考えた。自分らの都合を押し付けるんじゃなくて、ちゃんとした32Bitを提供してあげようと。
int32って型が用意されている。ファイルに書き出す時は、書きのように使えとな。 折角int32ってモジュールを作ったなら、こういうのも入れておいと欲しいぞ。
let output_int32 out_channel i = output_byte out_channel (Int32.to_int (Int32.shift_right i 24)); output_byte out_channel (Int32.to_int (Int32.shift_right i 16)); output_byte out_channel (Int32.to_int (Int32.shift_right i 8)); output_byte out_channel (Int32.to_int i) ;;
その他、int64とか、ネイティブintなんて型もあって、面倒くさいぞ。
examples
ocamlを入れたはいいが、何か例が欲しい。portsを漁ったら、下記のURLを紹介された。 http://cristal.inria.fr/caml_examples/ 取ってきて、フランスの香りに触れてみよう。
フランスの数学者パスカルにちなんで名前が付けられたプログラミング言語pascalですよ。 こいつをocamlで作っちゃえってやつ。
[sakae@pcbsd ~/ocaml-examples-3.12/pascal]$ cat fib1.p program fibonacci; var n: integer; function fib(n: integer): integer; begin if n < 2 then fib := 1 else fib := fib(n - 1) + fib(n - 2) end; begin n := 30; write(fib(n)) end [sakae@pcbsd ~/ocaml-examples-3.12/pascal]$ ./ipascal fib1.p 1346269
上のは、インタプリタ版のpascal。n := 30; って所が、オリジナルでは read(n); って なってた。どうやって数値を渡せばいいんだい。面倒なので即値を書いておいた。
[sakae@pcbsd ~/ocaml-examples-3.12/pascal]$ ./cpascal fib1.p add r 0, 30, r 1 store r 0, 0, r 1 # n sub sp, 4, sp load r 0, 0, r 1 # n store sp, 0, r 1 jmp Ffib, ra add sp, 4, sp write stop Ffib: sub sp, 8, sp :
こちらは、コンパイル版。想定してるアセンブラは何? フランスの情報試験に出て来る アセンブラ仕様? ソース嫁かな。精神に異常をきたしそうだな。そんな時は、 精神分析医にかかりましょう。フランス人と英語を話す医者が待機してますよ。
[sakae@pcbsd ~/ocaml-examples-3.12]$ ls doct* docteur: Imakefile Makefile docteur.ml loadall.ml doctor: Imakefile Makefile doctor.ml loadall.ml
ひょっとして有名な精神科医フロイトは、これまたフランス人かと思ったら、残念ながら オーストリア人でした。フランスが誇るパスツールさん関係のやつはないかな?
日本にも(香山)リカちゃんが居るんで、日本人バージョンのdoctorを作って欲しいぞ。 香山リカ講演依頼 に依頼すればいいのかしらん?