よりいろんな言語でフィボナッチ

恒例のフィボナッチベンチで V8 と Smalltalk、Ruby、Python、Scheme とを戦わせてみる - Smalltalkのtは小文字ですをまねっこ。
C++,C,OCaml,Java,F#,C#,Haskell,Scheme,JavaScript,Python,Ruby,Perl,ioでのフィボナッチ(36)。
あのフィボナッチさんもいまや中年だな。実行環境はWindows上のVMware上のLinux


Smalltalkなくてすみません。じつはこれ昔やったものなんだけどそんときなんか挫折した記憶が。

template  struct fib { enum{fn = fib::fn + fib::fn}; };
template <> struct fib<0> { enum{fn = 1}; };
template <> struct fib<1> { enum{fn = 1}; };

int const f = fib<36>::fn;

#include 

int main(){
	printf("%d\n", f);
	return 0;
}

./fib_cpp.exe 0.004345sec
                                                                                                          • -
#include int fib(int n){ return n < 2 ? 1 : fib(n-2)+fib(n-1); } int main(){ printf("%d\n", fib(36)); return 0; } ./fib_c-O3.exe 0.134033sec
                                                                                                          • -
open Pervasives let rec fib n = if n < 2 then 1 else fib(n-2) + fib(n-1);; print_int (fib 36); print_string ("\n"); ./fib_mlo.exe 0.30398sec
                                                                                                          • -
public class fib { public static int f(int n){ return n < 2 ? 1 : f(n-2)+f(n-1); } public static void main(String[] args) { System.out.println(f(36)); } } java fib 0.358354sec
                                                                                                          • -
#include int fib(int n){ return n < 2 ? 1 : fib(n-2)+fib(n-1); } int main(){ printf("%d\n", fib(36)); return 0; } ./fib_c.exe 0.542787sec
                                                                                                          • -
open Pervasives let rec fib n = if n < 2 then 1 else fib(n-2) + fib(n-1);; print_int (fib 36); print_string ("\n"); mono fib_fs-O3.exe 0.564644sec
                                                                                                          • -
open Pervasives let rec fib n = if n < 2 then 1 else fib(n-2) + fib(n-1);; print_int (fib 36); print_string ("\n"); mono fib_fs.exe 0.567634sec
                                                                                                          • -
using System; class Program { static int fib(int n){ return n < 2 ? 1 : fib(n-2)+fib(n-1); } static void Main(string[] args) { Console.WriteLine(fib(36)); } } mono fib_cs.exe 0.595356sec
                                                                                                          • -
fib n | n < 2 = 1 | otherwise = fib(n-2) + fib(n-1) main = putStrLn(show(fib(36))) ./fib_hs-O.exe 2.121945sec
                                                                                                          • -
(define (fib n) (if (< n 2) 1 (+ (fib (- n 2)) (fib (- n 1))))) (display (fib 36)) (display "\n") gosh ./fib.scm 4.140425sec
                                                                                                          • -
var fib = function (n){ if (n < 2){ return 1; } return fib(n-2) + fib(n-1); } print(fib(36)) js ./fib.js 14.837408sec
                                                                                                          • -
def fib(n): if n < 2: return 1 return fib(n-2)+fib(n-1) print fib(36) python ./fib.py 19.355325sec
                                                                                                          • -
def fib(n) n < 2 ? 1 : fib(n-2)+fib(n-1) end p fib(36) ruby ./fib.rb 26.329319sec
                                                                                                          • -
sub fib{ my $n = shift; $n < 2 ? 1 : fib($n-2)+fib($n-1); } print(fib(36)); print "\n"; perl ./fib.pl 31.538763sec
                                                                                                          • -
fib := method(n, if(n<2, 1, fib(n-2)+fib(n-1) )) fib(36) println io ./fib.io 515.357514sec
                                                                                                          • -

AutoPagerizeを書いた

AutoPagerizeすばらしいですよね。
そしてそれに慣れてくると未対応のページであんだよと思うことしきり。


ということでbk1の検索ページと購入履歴のSITEINFOを書いてみました。

{
    url:          'https://www.bk1.jp/myaccount/order/',
    nextLink:     '//a[text()="次へ→"]',
    pageElement:  '//table[@class="tbl"]',
    exampleUrl:   '',
},
{
    url:          'http://www.bk1.jp/webap/user/SchDetailBibList.do',
    nextLink:     '//a[text()="次へ→"]',
    pageElement:  '//table[@cellspacing="0" and @cellpadding="0" and @border="0" and @width="90%"]',
    exampleUrl:   '',
},

まずAutoPagerize書くときはスクリプトの上の方のDEBUG変数をtrueに。これで過程がエラーコンソールに出ます。
あと記法はXPathって言うので要素をとりだしてるらしい。FireBugでhtml見ながら、対象部分をXPathで書きます。

今回、引っかかった点としてはAutoPagerizeのソースをUTF8で保存しないとnextLinkが引っかからないこと。


以上でとても便利になりました。

デバッガーとかの話

デバッガ - higepon blog

デバッガー好き好き派の俺です。


バックグラウンドとしては結構裕福な組み込みでC言語で開発します。


んで僕のやり方は組み込みのコードを出来るだけPC環境に移植して、開発の大半をPC上で進めれるようにします。
ハードにかかわる部分とかはなんか適当にコメントアウトしたり、書き換えたりで強引に動かすようにする。


それで普段はVMware+Linux+Emacsでassertがしがしprintfでログもたくさん、と、若干ユニットテスト風なテストコード。
これでコード書く→コンパイル、実行を小さいサイクルで繰り返す。


ちなみにビルド手順はrake。


んでassert引っかかったらデバッガーの出番。こんどはVisual Studioに移動します。
移植段階でVSでも動くようにしておくのです。


それでログ見てちょっと怪しい部分書き換えたりしてブレイク張ってデバッガーでトレース。


大体は単純なミスなんですぐ直せます。


C言語的なバグとデバッガーは相性いいんじゃないかなあとかなんとなく思ってるけど深く考えてないです。

IronPythonでXNAで線を引く

import clr

clr.AddReference('System')
clr.AddReference('Microsoft.Xna.Framework')
clr.AddReference('Microsoft.Xna.Framework.Game')

from System import *
from Microsoft.Xna.Framework import *
from Microsoft.Xna.Framework.Graphics import *

class Game1(Game):
    def __init__(self):
        self.graphics = GraphicsDeviceManager(self)

        a = [VertexPositionColor(Vector3(0.0, 0.0, 0.0), Color.Black),
             VertexPositionColor(Vector3(1.0, 1.0, 0.0), Color.Black),
             VertexPositionColor(Vector3(0.0, 0.0, 0.0), Color.Red),
             VertexPositionColor(Vector3(-1.0,-1.0,0.0), Color.Red),
             VertexPositionColor(Vector3(-1.0, 1.0,0.0), Color.Blue),
             VertexPositionColor(Vector3(1.0,-1.0, 0.0), Color.Blue)]

        self.points = Array[VertexPositionColor](a)

    def Initialize(self):
        Game.Initialize(self)

    def LoadGraphicsContent(self, loadAllContent):
        self.declaration = VertexDeclaration(
            self.graphics.GraphicsDevice, VertexPositionColor.VertexElements)
        self.effect = BasicEffect(self.graphics.GraphicsDevice, None)

        self.graphics.GraphicsDevice.VertexDeclaration = self.declaration
        self.effect.VertexColorEnabled = True

        Game.LoadGraphicsContent(self, loadAllContent)

    def UnloadGraphicsContent(self, unloadAllContent):
        self.declaration.Dispose()
        self.effect.Dispose()

        Game.UnloadGraphicsContent(self, unloadAllContent)

    def Draw(self, gameTime):
        self.graphics.GraphicsDevice.Clear(Color.White)

        self.effect.Begin()
        for pas in self.effect.CurrentTechnique.Passes:
            pas.Begin()
            self.graphics.GraphicsDevice.DrawUserPrimitives[VertexPositionColor](
                PrimitiveType.LineList, self.points, 0, 3)
            pas.End()
        self.effect.End()

        Game.Draw(self, gameTime)

Game1().Run()

線を引きます。なんかXNAのhelpのサンプルのまるうつし。
ここで前に書いたタイプパラメーターが出てますね。なんか位置情報を配列に入れて描画担当に渡すんだけどさ、そんときの配列が生Python配列だとだめで、一回、位置情報型のArrayを作ってそれに生配列をいれるみたいな。な。

でも生配列→位置情報配列はそのままいけるという。

IronPythonでXNA

import clr

clr.AddReference('System')
clr.AddReference('Microsoft.Xna.Framework')
clr.AddReference('Microsoft.Xna.Framework.Game')

from System import *
from Microsoft.Xna.Framework import *
from Microsoft.Xna.Framework.Graphics import *

class Game1(Game):
    def __init__(self):
        self.graphics = GraphicsDeviceManager(self)

    def Initialize(self):
        self.spriteBatch = SpriteBatch(self.graphics.GraphicsDevice);

        Game.Initialize(self)

    def LoadGraphicsContent(self, loadAllContent):
        if (loadAllContent):
            self.texture = Texture2D.FromFile(self.graphics.GraphicsDevice, "../Content/Texture.png")

        Game.LoadGraphicsContent(self, loadAllContent)

    def Draw(self, gameTime):
        self.graphics.GraphicsDevice.Clear(Color.CornflowerBlue)

        self.spriteBatch.Begin()
        self.spriteBatch.Draw(self.texture, Vector2(0, 0), Color.White)
        self.spriteBatch.End()

        Game.Draw(self, gameTime)

Game1().Run()

IronPythonXNA
座標指定で画像(テクスチャー)を表示するだけのもの。基本的に基本のまま移植なんだけど一点、Content Pipelineなる仕組みを使ってないつーか使い方が良く分からないのでテクスチャーのロード部分がこんな感じになります。
あと継承してのスーパーなメソッド呼ぶ部分(Game.Draw(self, gameTime)とか)が警告になる。理由はしらね。


Pythonはあれだね、selfがうざいわ。インデントが有意なのはどうでもいいや。

generics,generic,ジェネリクス,ジェネリック

なんでジェネリクって言わないんだ。言え。


さて、IronRubyがまだまだだからIronPythonいじってますが、すでにライブラリーで定義されてるある総称型関数、テンプレートメソッド、を呼ぶのにタイプパラメーター、型パラメーター、type paramaterの指定をする必要があったのです。


そのやり方。

Module.Method[type](arg)

via 2007-11-11より。


これのtypeの部分が肝で、ようは型を大括弧でつつんで渡すのですね。ちなみにIronRubyで試したら大括弧ではだめでした。どうするんだろう。


あと参照した日記では型パラメーターを2つにした場合に例外、とありますが、今のIronPythonだと大丈夫です。ただ関係ない部分でPythonコードの修正がありますが。

# IronPythonのコード
import clr
clr.AddReference('Example')

import sys
import Example

d = Example.D()
d.M[long,long](123,456)

こんなんで呼べます。

PowerShellの価値

オブジェクト指向なコマンド環境「Powershell」を試してみた - てっく煮ブログ 跡地
はてなブックマーク - オブジェクト指向なコマンド環境「Powershell」を試してみた - てっく煮ブログ 跡地



ここのブックマークコメントを読んだんだけどなんかPowerShellのとらえ方にずれを感じるコメントが多かった。


Dos窓とかCygwinとか(ましてPythonとか)と比較するのはちがくね?


PowerShellが面白いのは.Net上に完全に乗ってることであってスクリプティングの能力とか2の次でしょ。


偉大なのはWindowsオブジェクト指向のFrameworkとして規定しなおした.Netで、PowerShellはその上で普通に実装した普通のシェルで
(いやまあ言語機能をちゃんと調べてないから実はとても面白い言語かもしれないけど)
だからまあもろもろがオブジェクトなのも当然だし。


だからもとの記事の「.NET Frameworkインタラクティブシェル」というのがまったくまっとうな評価で、.Net上に乗ってあらゆるオブジェクトをグルーしていける感を味わえ、さらその先がどうなるのかに思いをはせれるのがPowerShellの一番すてきな部分だと思うがどうか。


Squeakやれという話ですかそうですか。