2012年2月27日月曜日

Trampoline

トランポリンをご存知でしょうか。
相互再帰を最適化するものです。
私はプログラミングClojureを読んではじめて知りました。

相互再帰を最適化すると言っても、既存のものを最適化することは出来ません。
最適化のためには関数をトランポリンを使ったものにしなくてはなりません。

さて、そのトランポリンですが、実はScalazには用意されているのです!

多分6.0.4から入った・・・と思う。
私がStack Overflowで質問したからですね!フフン!

まぁ、たぶん質問しなくても入ってたと思いますが・・・・

なぜTrampolineが入ったのか

以下推測

それは、IOモナドの最適化のためだと思われます。

以前のIOモナドは、>>=で連結していくと評価時にIOの呼び出しが深くなってしまい、StackOverflowErrorを起こしていました。

そこで、トランポリンを導入することで最適化がされました。

命名規則をみると、Scalaz7から輸入されたようです。

なので、IOが問題になっていなかったら、Scalaz6では入っていなかったかも・・・?

使い方

プログラミングClojureの例を参考に偶数、奇数を調べる関数を書いてみる。

まずはトランポリンを使わずに


どれくらいでスタックがあふれるか調べる。


6桁で落ちるとは・・・・

トランポリン版


実行するにはrunメソッドを呼びます。


これは全く落ちない。
あと多分速い。

※追記
遅かった・・・・

結論

プログラミングClojureにあるとおり、なるべく最適なアルゴリズム、自己再帰で書きましょう。
IOモナドのような特殊なケースはあまりないと思います。

さて、このTrampoline、じつはtype aliasです。
type Trampoline [+A] = Free[Function0, A]
と定義されており、Freeがもっと一般化されたなにかであることがわかります。

Freeについてはいつか調べるor誰か調べてくれる・・・はず・・・・・

2012年2月17日金曜日

type Self


に対し、りりかるろじかるさんが反応をくれたので書いてみます。

最初に、これが何の役に立つかですが、


と定義したとき、


となります。

ポイントは、
  • Barからfを呼び出すとBarが返る。
  • Barからgを呼び出すとOption[Bar]が返る。
  • fの返り値からhを呼び出せる。
といったところでしょうか。

つまり、スーパークラスでサブクラスの値を返すことができるということです。

しかし、これにはサブクラスがいちいちSelfを定義しなければいけないので楽したいですよね。
そこで、りりろじさんに考えて頂いた方法を書いていきます。

this.type

this.typeを使って定義すると、


となります。

Bar.this.typeが要求されているところでBarを渡すとコンパイルエラーがでます。
なので、asInstanceOfを使って定義します。


なんかエラー出てる・・・・
うーん、これはどういうことでしょう?
gの返り値をOption[this.type]と明示的に書いても変わりません。
むむむむむ・・・・・えらいひと、教えて下さい。

型パラメータ

Genericsまんせー
ということで書いてみる。


おお、ちゃんと動きますね。

この型パラメータ版とtype Self版で比べてみると、
  • 型パラメータ有無
  • どちらも、型の情報がなくなると意味がない
  • 継承元がtype Selfを書くか、型パラメータに型を書くか
などあります。

型パラメータを使ったほうが楽に書けそうですが、type Selfを使うと楽になることもあります。


このように、複数のtraitでSelfを使う場合はこの書き方が有利なようです。


他にもっといい方法があったら是非教えてくださいねー!

2012年2月11日土曜日

Scalaでポイントフリースタイル

関数合成の話がTLであったので書いてみる。

最近だとゆろよろさんの記事が面白い。
http://d.hatena.ne.jp/yuroyoro/20120203/1328248662
http://d.hatena.ne.jp/yuroyoro/20120206/1328513534

Category

とりあえずCategoryから。

Categoryとか知らない人は
https://github.com/quassia88/introduction-to-category-theory-in-scala-jp/wiki
を見て、なんとなく分かってみてください。

この圏論入門の記事だとCategoryのインスタンスはFunctionしか書いてなくて、抽象化をしていることがわかりにくいですが、ScalazではCategoryのインスタンスにFunction, PartialFunction, Kleisliがあります。

※コード例はScalaz7


idが恒等関数、composeが合成関数です。

>>>, <<<というシンタックスもあります。


Arrow

究極的には関数合成だけでプログラムを書くこともできますが、>>>だけではなかなか難しいところがあります。

そこで登場するものが***と&&&。
この2つは関数を並列に合成します。

***はA => BとC => Dから(A, C) => (B, D)を返します。
&&&はA => BとA => CからA => (B, C)を返します。



関数合成を意識して、n番目のフィボナッチ数を得る関数を書いてみます。


|>はパイプ演算子と言われるもので、値を関数に適用するものです。

並列合成の使いどころは、ある値を複数回使うときです。

ScalazではTupleでfoldが使えるので別々に計算したものを簡単にまとめることが出来ます。

Scalaでも、Let's point free!

2012年2月5日日曜日

ClojureとFXMLとRuby

この前Clojureで試したのですが、fx:idが使えず微妙な感じでしたが、解決方法を見つけました!

JavaFXではfx:scriptタグというのがありますよね?

このタグにJavaScriptのコードを書いているサンプルコードをよく見ますが、実はこれ、
JavaScript以外でも動くのですよ!

いや、まずJavaScriptが動いているという時点でなにか疑問を持たなければいけなかったのですが。

fx:script

この機能はJSR-223で実現されています。
恐らく。

この機能標準ライブラリにあることを最近知りました。
わざわざダウンロードしていたのは何だったのか・・・・・

fx:scriptを使うためには、言語を指定します。

この時に、FXMLLoaderはgetEngineByNameを使ってスクリプトを実行するためのScriptEngineを取得します。

なので、JSR-223に対応している言語ならば動くのですよ!

とりあえず、安定して動きそうなJRubyを試してみました。


実行



なぜか重いけど動く・・・!

eventはグローバルな変数で、アクションを起こしたい時はこいつを渡しておけばいいようです。

JRubyではgetは書かなくていいし、setも=を使って書けるしなかなか楽ですね。

fx:id

さて、これでfx:idの値を参照してみます。


実行



動いたー!

Clojureで試す

なぜ最初からClojureで動かさなかったのか、それは動かなかったからです。

で動かしてみましょう、ぬるぽが出るはずです。

そこで、"clojure jsr 223"でぐぐってみるとこんなプロジェクトが。
http://code.google.com/p/clojure-jsr223/

そう、clojure標準ではJSR-223に対応していなかったのです。

なのでこのライブラリをdependenciesに追加すれば動くようになります。


fx:scriptを後ろに置いたのは、labelが見えないと怒られるからです。


これにてこの問題は解決です。

メジャーなScript言語はJavaFXで動くので、是非試してみて下さい。

2012年2月3日金曜日

Tagged, Union

Scalaz7のSNAPSHOTがリポジトリにあったので、いろいろ試しています。

設計が大幅に変わったので6系にべったりだと移行はかなり大変な気がします。

Tagged

Scalaz7ではNewTypeがなくなり、代わりにTagged Typesというものが入りました。

これは既存の型にタグを付けることで、コンパイラに別の型のように見せることができます。
さらに、この型は元の型が必要な場合にはunboxされるという素敵なものです。


@@がタグを付けるためのものです。
ここではIntにFooタグを付けたものをBarとしました。


この型を取る関数にIntを渡すとコンパイルエラーになります。


エイリアス付けるとTagを使ったときに推論が効かないので、@@を直接書くか、型パラメータをとるようにするといいです。

Scalaz7ではNewTypeを使っていた殆どはTagged Typesに置き換えられました。
あまりなにも考えずNewTypeばかり継承していると移行が大変ですのでこのことも考えておきましょう。 (体験者談)

Tagged Typesについて詳しく知りたい場合はこちらを。

Union

最近入って、SNAPSHOTにもまだ入ってないもの。
型の和が簡単に作れてしまう優れもの。
これもunboxされる。


t[A]#t[B]でAとBの和を作ります。
この型を直接引数に取るのではなく、Containsという型を使います。


Converterで値を持てるけど、Anyになってしまうので微妙。

Tagged Typeにも言えますが、Unionはsealed traitとcase classで新しいデータ構造を作るより手軽に使えるところがいいところですね。

Scalaz7は全体的に効率化がされていて、Unboxedなこれらの型もそのためにあるのだと思います。

便利な上に効率もいいのでガンガン使ってしまいましょう。

早くScalaz7が出て欲しいなぁ。

2012年2月2日木曜日

ClojureとFXML

JavaFX for Linux キタ━(゚∀゚)━!
ということでさわってみました。

ただ動かすのも面白くない、というかJava面白くない、ということでClojureから呼び出してみました。

JavaFXで私が一番注目していたものはFXML。
XMLは好きじゃないけど、ちゃんとロジックが分離できそうだし、GWTのUiBinderを気に入っていたので楽しみにしていました。

というわけでClojure+FXMLで書いてみました。

プロジェクトの設定(Linux)

Leiningenを使います。

多分Winの場合はそのまま動く。
Linuxの場合は http://www.oracle.com/technetwork/java/javafx/downloads/devpreview-1429449.html から Linux 32-bit をダウンロードして、 lib に jfxrt.jar を、 bin に *.so を置いて下さい。

main.clj

まずはApplicationを継承した起動ポイントを書く。


main/launchだとエラーが出る謎。

pane.clj

xmlをFXMLLoaderでロードするだけ。


root.xml

fx:controllerを指定してButtonを置いてonActionを設定する。


controller.clj

Buttonから呼び出される関数を定義する。


gen-classに:methodsをわざわざ書くのがめんどう。

実行



なんかあっさり動いてしまった。

これでバリバリClojureでGUIが書けるぞー










と思ったらそんなことなかった。

fx:id

Buttonを押したらLabelのテキストが変わるようにしてみたい。
そんな場合はfx:idでControlに名前をつけるとコントローラで扱えるようになる。
その時にコントローラはmutableFXMLアノテーションが付いたフィールドを持っていなければならない。

gen-classでフィールドは指定できない。
Clojureでは:stateを使うことで状態を実現している。

一番最初に思いついたものはdeftypeを使う方法。

deftype

deftypeではmutableなフィールドを持てます。
なのでdeftypeでコントローラを作ってみます。


でもこれだと、コンストラクタが引数をとるのでFXMLLoaderがインスタンスを作れない。
なのでこれを更に継承・・・・・出来なかった。
なぜならdeftypeで作ったクラスはfinalが修飾されている。
メソッドの型も曖昧なままなので継承できたとしても動くかどうかはわからない。

こうなると別の方法を取るしかないですね。

別の方法といってもClojureでclassを作るにはdeftype, defrecord, gen-classしかない。
deftypeは先程の通りコンストラクタが引数をとってしまう。
defrecordではそもそもmutableなフィールドを持てない。
gen-classはフィールドを指定できない。

Javaを使うことを・・・強いられてるんだ!

ここで登場Java!
嫌いじゃないけど使いたくないJava!

Java側でmutableでFXMLアノテーションが付いた変数を宣言しておこうという戦略。


これを継承してさあ実行。


javafx.fxml.LoadException: Value is already set.


\(^o^)/

ヤンナルネ・・・・・

結果

onActionで関数を指定して呼び出すことはできたがfx:idが使えなかった。

誰か解決方法があったら教えて下さい!