retro on F#
『おみやげと鉄道』(講談社)なんて本を読んだ。おみやげって英語では、スーベニアって 言うんだけど、日本で言うおみやげとスーベニアには、性格に違いが有ると言う。
欧州圏でのスーベニアは、旅のメモリアルを主目的にしてるらしい。それに対して土産は、 旅に行ってきましたよ。ほれ、これがその証拠とばかり近隣に配るのが連綿と続いている ようだ。
会社時代、非常に出張が多かった。職場への土産は、まあ潤滑油だな。誰彼となく出張に 行くもので、あちこちの土産が溢れていたよ。時々、外国から来る同僚なんかが居て、 結構外国の土産も堪能出来たなあ。まあ、普通に言ったら、土産ってのは食べ物に決まって いる。食べたら無くなるから、良いのだ。
自分用の土産は、残る物が有ったな。かさばる物は駄目って事で。スイスの超美しい地図。 本場ギネスのコースター。ゾーリンゲンの鋏とか。食べ物って言うと、アラスカの空港で 売ってた、スモークサーモン。これとセットで、バーボンウィスキーとか。これを買うのが 楽しみでしたよ。
件の本に色々な土産が載ってた。昔住んだ事がある仙台。仙台と言えば『萩の月』が有名。 これが全国に知れ渡るようになったのは、その頃仙台、福岡間に路線を持っていた東亜国内航空の 機内スナックに採用されたかららしい。由緒ある物だと思っていたけど、そうじゃ無かったのね。 初めて知りましたよ。
初めて知ると言うと、東京名物とばかり思っていた、ひよこのお菓子と言うか饅頭もどきのやつ。 出身は、九州は飯塚だそうだ。全国区に販路を拡げたんだな。萩の月は、これとは対象に 地方区より外には出ていない。食べたかったら仙台方面まで足を延ばしてくださいって事だ。
大阪にアリバイ横丁ってのがあるらしい。そこでは全国各地の土産を売っていて、ほら仙台に 行ってきたんだよと証拠品を買い求める事が出来るらしい。尤も、そういうものに頼らなくても 、アンテナショップに行けば置いてあるのかな?
retro.fsx
再びしつこくretroします。vmの所を見ていると、retro.fsxなんてファイルが置いてある。 fsxなんて特撮ですか? ファイルを開いてみるとどうもmlっぽい。何故mlと推測したかと 言うと、特徴的なletとmatchってのが有ったからです。こういうサフィックスを 付けるのはM$かな。とするとF#語で書かれてるんだな。
えっと、F#を動かすには、M$お得意の毎年更新されるvisual stdioを入れて、それから M$研究所へ行って、F#を取ってくるのかな。でも、家の掟として、visual stdioとeclispeと 言うGUI系は入れてはいかんとなってるしなぁ。諦めろ。諦められない!
最後の望みをFreeBSDに託して、portsの下を漁ってみると、lang/fsharpなんてのが出て きたぞ。俄かに信じられんな。広告を読んでみた。
F# is an open-source, strongly typed, multi-paradigm programming language encompassing functional, imperative and object-oriented programming techniques. F# is most often used as a cross-platform CLI language, but can also be used to generate JavaScript and GPU code. F# is developed by The F# Software Foundation and Microsoft. An open source, cross-platform edition of F# is available from the F# Software Foundation. F# is also a fully supported language in Visual Studio. Other tools supporting F# development include Mono, MonoDevelop, SharpDevelop and the WebSharper tools for JavaScript and HTML5 web programming. F# originated as a variant of ML and has been influenced by OCaml, C#, Python, Haskell, Scala and Erlang. WWW: http://fsharp.org/
で、http://fsharp.org/へ行ってみましたよ。そしたら、確かに FreeBSDでのF#の作り方が出てた。それによると、monoってのが最初に必要らしい。monoって 一体何? やはり広告を読んでみた。
Mono is an open source implementation of .NET Development Framework. Its objective is to enable UNIX developers to build and deploy cross-platform .NET Applications. The project implements various technologies developed by Microsoft that have now been submitted to the ECMA for standardization. Mono provides the necessary software to develop and run .NET client and server applications on BSD, Linux, Solaris, Mac OS X, Windows, and Unix. WWW: http://www.mono-project.com/
ドット・ネットの土台なのね。待つ事数十分。出来上がりましたよ。fsharpiってのが F#のインタープリタで、fsharpcってのがコンパイラか。早速コンパイラを試してみる。
[sakae@pcbsd ~/src/ml]$ fsharpc retro.fsx F# Compiler for F# 3.0 (Open Source Edition) Freely distributed under the Apache 2.0 Open Source License /usr/home/sakae/src/ml/retro.fsx(114,13): warning FS0058: Possible incorrect indentation: this token is offside of context started at position (113:22). Try indenting this token further or using standard formatting conventions. /usr/home/sakae/src/ml/retro.fsx(114,13): warning FS0058: Possible incorrect indentation: this token is offside of context started at position (113:22). Try indenting this token further or using standard formatting conventions.
ml系にはオフサイドが無いと思っていたけど、ここら変はhaskellの真似をしてるのね。 2回も同じ警告が出てくるけど、ちょっとしつこくないかい。あそうか、2PASS方式で コンパイルしてるんか。 で、 出来上がったのは、いやーんになっちゃうexeですよ。
[sakae@pcbsd ~/src/ml]$ file retro.exe retro.exe: PE32 executable (console) Intel 80386 Mono/.Net assembly, for MS Windows
Windowsへ持って行って実行しろとな。それともワインを入れろ? ワイン用の葡萄なら そこら辺にたくさんあるんだけど、今回は遠慮して、Windows7でやってみます。
sakae@NIL ~/retro $ ./retro.exe ハンドルされていない例外: System.IO.FileNotFoundException: ファイルまたはアセン ブリ 'FSharp.Core, Version=4.3.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d5 0a3a'、またはその依存関係の 1 つが読み込めませんでした。指定されたファイルが見つ かりません。 場所 <StartupCode$retro>.$Retro$fsx.main@() Signal 67
ははは、見事にエラー。でも相変わらずアホなメッセージを出すな。指定されたファイルって、 何やねん。一番大事な事が抜けてるな。これがM$の流儀だからしょうがないか。
文句を言っててもしょうが無いので、前向きに対処しよう。マニュアルは無いようなので 本体に同梱されてないか試してみた。
[sakae@pcbsd ~/src/ml]$ fsharpc --help : --standalone Statically link the F# library and all referenced DLLs that depend on it into the assembly being generated :
全部入りってモードが指定出来るのね。これなら、何か足りないとは言われはしないだろう。 その代わり出来上がったものは肥大化するけどね。
sakae@NIL ~/retro/benchmarks $ time ../main.exe real 0m4.239s user 0m0.000s sys 0m0.031s sakae@NIL ~/retro/benchmarks $ time ../sretro.exe real 0m7.925s user 0m0.015s sys 0m0.031s
golangとのスピード比べには負けてしまいましたよ。
mono
fsharpを入れる時の説明を読んでたら、/usr/local/etc/monoの下のレイジストリィを いじれなんて事が書いてあった。そんなファイル無いんだけどな。
[sakae@pcbsd /usr/local/etc/mono]$ ls -F 2.0/ 4.5/ config 4.0/ browscap.ini mconfig/
4.0とかあるのは、Windowsにいろいろ入ってるNETフレームワークの事だな。でも何となく configってファイルが気になるんで、ちょっと見てみる。
<configuration> <dllmap dll="i:cygwin1.dll" target="libc.so.7" os="!windows" /> <dllmap dll="libc" target="libc.so.7" os="!windows"/> <dllmap dll="intl" target="libintl.so" os="!windows"/> :
この設定ファイルって、Windows側とFreeBSD側のライブラリィーの対応表じゃなかろうか。 osがwindowsじゃ無い場合って、cygwinの事なんだな。わざわざ、こんな物を用意してるって 事は、ひょっとして、fsharpcでコンパイルした、exeファイルも、そのままFreeBSDで 動くに違いない。ぐぐる様に聞いてみましたよ。
.NETアプリをLinux対応にするMono なんてのを教えてもらった。monoってコマンドが、Windows上のネット・フレームワークの まねをしてくれるのね。
[sakae@pcbsd ~/src/retro/benchmarks]$ time ../main real 0m4.340s user 0m4.139s sys 0m0.063s [sakae@pcbsd ~/src/retro/benchmarks]$ time mono ../retro.exe real 0m13.126s user 0m11.762s sys 0m1.254s [sakae@pcbsd ~/src/retro/benchmarks]$ time fsharpi ../retro.fsx /usr/home/sakae/src/retro/retro.fsx(114,13): warning FS0058: Possible incorrect indentation: this token is offside of context started at position (113:22). Try indenting this token further or using standard formatting conventions. real 0m46.291s user 0m25.528s sys 0m20.048s
ふむ、FreeBSD上で(無理して)exeファイルを動かすと、Windows上で素直に動かすよりも 2倍時間がかかっているな。インタプリタで動かすと、rubyやPythonで動かすよりも断然 速い。インタプリタは、ソースファイルを1回しかスキャンしないのね。なんて事が 分かったよ。
ついでに、monoって何よってのをmanを引いておく。
DESCRIPTION mono is a runtime implementation of the ECMA Common Language Infra- structure. This can be used to run ECMA and .NET applications. The runtime contains a native code generator that transforms the Common Intermediate Language into native code. The code generator can operate in two modes: just in time compilation (JIT) or ahead of time compilation (AOT). Since code can be dynami- cally loaded, the runtime environment and the JIT are always present, even if code is compiled ahead of time. The runtime loads the specified file and optionally passes the argu- ments to it. The file is an ECMA assembly. They typically have a .exe or .dll extension. The runtime provides a number of configuration options for running applications, for developing and debugging, and for testing and debug- ging the runtime itself. The mono command uses the Boehm conservative garbage collector while the mono-sgen command uses a moving and generational garbage collector.
ATOとかJITが入ってますよ。ガベコレも入ってますよって事ですな。ATOとJITを試して みたけど、デフォルトとの差は誤差範囲でしたよ。今回みたいなベンチだと大いに ターボチャージャーみたいに効きそうな感じがするんですけど、そんなに甘い世界じゃ無い? 詳しい事は、ruby方面のあの人に聞いてみればいいのか。
あの人に聞くには、資料に何を用意すればいいの。取り合えず逆アセンブラの結果でも 見せればいいのかな?
[sakae@pcbsd ~/src/ml]$ monodis retro.exe .assembly extern mscorlib { .ver 4:0:0:0 .publickeytoken = (B7 7A 5C 56 19 34 E0 89 ) // .z\V.4.. } .assembly extern FSharp.Core { .ver 4:3:0:0 .publickeytoken = (B0 3F 5F 7F 11 D5 0A 3A ) // .?_....: } .assembly 'retro' { .custom instance void class [FSharp.Core]Microsoft.FSharp.Core.FSharpInterface DataVersionAttribute::'.ctor'(int32, int32, int32) = ( 01 00 02 00 00 00 00 00 00 00 00 00 00 00 00 00 ) // ................ : // method line 37 .method assembly static default int32 readFile@74 (int32 h) cil managed { // Method begins at RVA 0x2594 // Code size 25 (0x19) .maxstack 4 .locals init ( int32 V_0) IL_0000: call class [mscorlib]System.IO.FileStream[] class Retro::get_files() IL_0005: ldarg.0 IL_0006: ldelem [mscorlib]System.IO.FileStream IL_000b: callvirt instance int32 class [mscorlib]System.IO.Stream::ReadByte() IL_0010: stloc.0 IL_0011: ldloc.0 IL_0012: ldc.i4.m1 IL_0013: bne.un.s IL_0017 IL_0015: ldc.i4.0 IL_0016: ret IL_0017: ldloc.0 IL_0018: ret } // end of method Retro::readFile@74 :
これも付けた方が良いのかな?
[sakae@pcbsd ~/src/ml]$ pedump retro.exe COFF Header: Machine: 0x014c Sections: 0x0003 Time stamp: 0x52185ec9 Pointer to Symbol Table: 0x00000000 Symbol Count: 0x00000000 Optional Header Size: 0x00e0 Characteristics: 0x010e PE Header: Magic (0x010b): 0x010b LMajor (6): 0x08 LMinor (0): 0x00 Code Size: 0x00003c00 Initialized Data Size: 0x00000200 Uninitialized Data Size: 0x00000000 Entry Point RVA: 0x00005abe Code Base RVA: 0x00002000 Data Base RVA: 0x00006000 : Data directories: Export Table: 0x00000000 [0x00000000] Import Table: 0x00005a64 [0x00000057] Resource Table: 0x00000000 [0x00000000] Exception Table: 0x00000000 [0x00000000] Certificate Table: 0x00000000 [0x00000000] Reloc Table: 0x00008000 [0x0000000c] Debug: 0x00000000 [0x00000000] Copyright: 0x00000000 [0x00000000] Global Ptr: 0x00000000 [0x00000000] TLS Table: 0x00000000 [0x00000000] Load Config Table: 0x00000000 [0x00000000] Bound Import: 0x00000000 [0x00000000] IAT: 0x00002000 [0x00000008] Delay Import Desc: 0x00000000 [0x00000000] CLI Header: 0x00002008 [0x00000048] Name: .text Virtual Size: 0x00003ac4 Virtual Address: 0x00002000 Raw Data Size: 0x00003c00 Raw Data Ptr: 0x00000200 Reloc Ptr: 0x00000000 LineNo Ptr: 0x00000000 Reloc Count: 0x0000 Line Count: 0x0000 Flags: code, exec, read, :
mcs, csharp
monoを入れると、M$がやっきになって宣伝してるC#のコンパイラとインタプリタが同時に インストールされる。以下は、cshapeのman部分。
DESCRIPTION The csharp is an interactive C# shell that allows the user to enter and evaluate C# statements and expressions from the command line. The regular mcs command line options can be used in this version of the compiler. The gsharp command is a GUI version of the C# interpreter that uses Gtk# and provides an area to attach widgets as well. This version can be attached to other Gtk# applications in a safe way as it injects itself into the main loop of a Gtk# application, avoiding any problems arising from the multi-threaded nature of injecting itself into a tar- get process. Files specified in the command line will be loaded and executed as scripts.
Javaもどき言語を手打ちで試す人って居るのかしらん? まあ、正統Javaに勝ちたい一心で ってのが、あるんでしょうなあ。
また、monoをGUIで使いたいって人用にmonodevelopなんてのが用意されてて、Windowsから 移ってきたクリック猿な人も安心。更に、mono-basicなんてのも有ったりして、幅広く Windows屋さんを呼び込むのみ貢献してる。日経ソフトウェアだか、日経Linuxあたりで 紹介されんかな。XPが時間切れで、Linuxへどうぞって事なら、外しちゃだめよ。
おまけ
retroのvmコレクションの中に、C#のコードが有ったので、試してみた。
[sakae@pcbsd ~/src/retro/vm/experimental/CSharp]$ mcs RetroForth.cs [sakae@pcbsd ~/src/retro/vm/experimental/CSharp]$ mv RetroForth.exe ~/src/retro/ [sakae@pcbsd ~/src/retro/vm/experimental/CSharp]$ cd ~/src/retro/benchmarks/ [sakae@pcbsd ~/src/retro/benchmarks]$ time mono ../RetroForth.exe real 0m4.971s user 0m4.744s sys 0m0.133s
ふーん。golangの後を追うって感じだな。猫でも分かるC# なんて本も出てるようだから、 遊んでみるには良いかも知れませんよ。おいらは手を出さないけど。
あっ、実験用コードって事で、ネットワーク上にパケットが流通するようにvmが拡張 されてる。そして、それを使った、TCPのサーバーとクライアントの例が出てた。 VM拡張の良い例になってるな。