2013年5月12日日曜日
2013年3月1日金曜日
2013年2月7日木曜日
Destructuringを使おう
Clojureで積極的にDestructuringを使っていこうという話です。
例: index-of
Destructuringを使うとこんな感じで書ける。
firstとrestがなくなりました。
例: end
Destructuringは関数の引数部に直接書ける。
リスト全体を束縛する変数を省略出来ました。
レコードに対する操作
例: abs
Destructuringを使うとこんな感じ。
{:keys [foo bar ...]}はフィールドを列挙することでその値を束縛します。
例: add
フィールドと違った名前の変数名を付ける場合は{foo' :foo bar' :bar ...}という記法が使えます。
Destructuringを使うことで要素の取得、束縛を簡素にしませんか?
ListやVectorに対する再帰
例: index-of
Destructuringを使うとこんな感じで書ける。
firstとrestがなくなりました。
例: end
Destructuringは関数の引数部に直接書ける。
リスト全体を束縛する変数を省略出来ました。
MapやRecordに対するDestructuring
レコードに対する操作
例: abs
Destructuringを使うとこんな感じ。
{:keys [foo bar ...]}はフィールドを列挙することでその値を束縛します。
例: add
フィールドと違った名前の変数名を付ける場合は{foo' :foo bar' :bar ...}という記法が使えます。
Destructuringを使うことで要素の取得、束縛を簡素にしませんか?
2013年2月2日土曜日
Clojureで継承みたいなナニカ
Clojureのdeftypeやdefrecordではinterfaceのみを実装することができます。
しかし、継承のように実装があるclassを継承したいときがあります。
例えばこんなコードがあります。
ConsとNilのaddとemptyの実装が同じです。
共通化したい。
とりあえず、addとemptyを別Protocolに。
ListというProtocolを作って、それに対するAdderを定義します。
ConsとNilに対してListを実装すれば、めでたしめでたし。
しかし、継承のように実装があるclassを継承したいときがあります。
例えばこんなコードがあります。
ConsとNilのaddとemptyの実装が同じです。
共通化したい。
とりあえず、addとemptyを別Protocolに。
ListというProtocolを作って、それに対するAdderを定義します。
ConsとNilに対してListを実装すれば、めでたしめでたし。
2013年1月29日火曜日
ClojureのKeywordはLensなのですy
春休みヤッター!
ブログの更新頻度も上げていくつもりです。
Lensはあるフィールドに対するgetterとsetterを持つ。
コードにするとこんな感じ。
見てわかるとおり、lgetはgetで、lsetはassocで十分なのだ。
getとsetがあればmodifyが定義できる。
Clojureにはupdate-inがある。
Lensは合成が可能だ。
Clojureの{get, assoc, update}-in関数は複数のKeywordをとることで、ネストしたレコードに対しても有効です。
LensはStateモナドと組み合わせると素敵です。
更新途中の状態を取得することは出来ないけれど、Clojureにはアローマクロが存在します。
KeywordがLensだということを意識すれば、Lensの考え方を応用することが出来ますね。
ブログの更新頻度も上げていくつもりです。
Lens
Lensはあるフィールドに対するgetterとsetterを持つ。
コードにするとこんな感じ。
見てわかるとおり、lgetはgetで、lsetはassocで十分なのだ。
Lensの特徴
getとsetがあればmodifyが定義できる。
Clojureにはupdate-inがある。
Lensは合成が可能だ。
Clojureの{get, assoc, update}-in関数は複数のKeywordをとることで、ネストしたレコードに対しても有効です。
LensはStateモナドと組み合わせると素敵です。
更新途中の状態を取得することは出来ないけれど、Clojureにはアローマクロが存在します。
KeywordがLensだということを意識すれば、Lensの考え方を応用することが出来ますね。
2012年12月17日月曜日
JavaFX & Web Start with Clojure
This article is the 5th of JavaFX Advent Calendar and a sequel of Tic-tac-toe with Clojure.
Tic-tac-toe
Since the logic of the game have been made, we only need to implement at the drawing.
As the basis for JavaFX, inherit javafx.application.Application to the main class.
In order to compile the class files of Java, we use the gen-class.
In the main method calls Application.launch.
In the start method implements tic-tac-toe.game.Canvas and register the handler in each panel.
doto is useful when using the GUI library in Clojure.
We can run continuously some methods under the instance.
It is like the instance_eval in Ruby.
Such an interface as EventHandler is obtained an instance by using reify.
First, make a standalone jar file with lein2 uberjar.
Then create a jnlp file.
The all-permissions are needed to run Clojure.
We must make a signature, because it requires all-permissions.
You can make the keystore by keytool, and sign the jar using jarsigner.
You can start with Web Start.
If you try on local environment, rewrite the codebase of jnlp file.
I think that JavaFX is simpler than Swing and we would be able to write the GUI application easily.
But I felt that the Web Start is not suitable for other required language runtime, such as the Scala and Clojure.
Because file size becomes very large.
Tic-tac-toe
Since the logic of the game have been made, we only need to implement at the drawing.
Application
As the basis for JavaFX, inherit javafx.application.Application to the main class.
In order to compile the class files of Java, we use the gen-class.
In the main method calls Application.launch.
In the start method implements tic-tac-toe.game.Canvas and register the handler in each panel.
doto is useful when using the GUI library in Clojure.
We can run continuously some methods under the instance.
It is like the instance_eval in Ruby.
Such an interface as EventHandler is obtained an instance by using reify.
Web Start
First, make a standalone jar file with lein2 uberjar.
Then create a jnlp file.
The all-permissions are needed to run Clojure.
We must make a signature, because it requires all-permissions.
You can make the keystore by keytool, and sign the jar using jarsigner.
keytool -genkey -keystore foo -alias bar jarsigner -keystore foo target/tic-tac-toe-0.1.0-SNAPSHOT-standalone.jar bar
You can start with Web Start.
If you try on local environment, rewrite the codebase of jnlp file.
Miscellaneous Thoughts
I think that JavaFX is simpler than Swing and we would be able to write the GUI application easily.
But I felt that the Web Start is not suitable for other required language runtime, such as the Scala and Clojure.
Because file size becomes very large.
2012年12月5日水曜日
ClojureでJavaFX & Web Start
JavaFX Advent Calendar 2012
5日目の記事です。
三目並べ
Cojureで三目並べの続き。
ここでは三目並べのJavaFX実装について書きます。
ゲームのロジックは作ってあるのであとは描画のところを実装するだけ。
JavaFXの基本として、メインクラスにjavafx.application.Applicationを継承します。
ここではgen-classを使って、Javaのclassファイルにコンパイルします。
mainメソッドではApplication.launchを呼び出します。
あとはstartメソッドでtic-tac-toe.game.Canvasを実装し、各パネルにhandlerを登録します。
ClojureでGUIライブラリを使うときに便利なのがdoto。
あるインスタンスのもとで、メソッドを連続して実行することが出来ます。
Rubyのinstance_evalのようなものですね。
EventHandlerなどのインターフェースはreifyを使うことで実体を得られます。
JavaFX Script時代にはいくつかWeb Startのアプリケーションを作ったことが
ありましたが、JavaFX 2になってからは初のWeb Startです。
まずは、lein2 uberjarでstandaloneなjarを作ります。
20MBもあるのはClojure+JavaFXのclassファイルが入ってる所為です。
次にjnlpですが、こんな感じになりました。
all-permissionsになっているのはClojureを実行するためです。
多分JRubyやGroovyでもall-permissionsが必要になるはず。
all-permissionsを要求するので、署名をしなければなりません。
keytoolで適当なkeystoreを作ります。
keytool -genkey -keystore foo -alias bar
fooというファイルが作られるので、jarsignerを使ってjarに署名します。
jarsigner -keystore foo target/tic-tac-toe-0.1.0-SNAPSHOT-standalone.jar bar
これでWeb Startで起動できます。
実際に試す場合はjnlpファイルのcodebaseを
codebase="file:/home/halcat0x15a/tic-tac-toe/"
のように書き替え、
javaws tic_tac_toe.jnlp
で実行可能です。
このプログラムではたいしたことをしていませんが、JavaFXのおかげで、Swingよりもシンプルで簡単にGUIを書けるようになったと思います。
他のGUIライブラリと比べても、ライブラリの設計は格段に良くなったと感じます。
Web Startは、ScalaやClojureなどのランタイムが他に必要な言語にはあまりむかないのかなと感じました。
プログラム+ライブラリ+ランタイムとなると、かなりファイルサイズが大きくなってしまいます。
5日目の記事です。
三目並べ
Cojureで三目並べの続き。
ここでは三目並べのJavaFX実装について書きます。
ゲームのロジックは作ってあるのであとは描画のところを実装するだけ。
Application
JavaFXの基本として、メインクラスにjavafx.application.Applicationを継承します。
ここではgen-classを使って、Javaのclassファイルにコンパイルします。
mainメソッドではApplication.launchを呼び出します。
あとはstartメソッドでtic-tac-toe.game.Canvasを実装し、各パネルにhandlerを登録します。
ClojureでGUIライブラリを使うときに便利なのがdoto。
あるインスタンスのもとで、メソッドを連続して実行することが出来ます。
Rubyのinstance_evalのようなものですね。
EventHandlerなどのインターフェースはreifyを使うことで実体を得られます。
Web Start
JavaFX Script時代にはいくつかWeb Startのアプリケーションを作ったことが
ありましたが、JavaFX 2になってからは初のWeb Startです。
まずは、lein2 uberjarでstandaloneなjarを作ります。
20MBもあるのはClojure+JavaFXのclassファイルが入ってる所為です。
次にjnlpですが、こんな感じになりました。
all-permissionsになっているのはClojureを実行するためです。
多分JRubyやGroovyでもall-permissionsが必要になるはず。
all-permissionsを要求するので、署名をしなければなりません。
keytoolで適当なkeystoreを作ります。
keytool -genkey -keystore foo -alias bar
fooというファイルが作られるので、jarsignerを使ってjarに署名します。
jarsigner -keystore foo target/tic-tac-toe-0.1.0-SNAPSHOT-standalone.jar bar
これでWeb Startで起動できます。
実際に試す場合はjnlpファイルのcodebaseを
codebase="file:/home/halcat0x15a/tic-tac-toe/"
のように書き替え、
javaws tic_tac_toe.jnlp
で実行可能です。
雑感
このプログラムではたいしたことをしていませんが、JavaFXのおかげで、Swingよりもシンプルで簡単にGUIを書けるようになったと思います。
他のGUIライブラリと比べても、ライブラリの設計は格段に良くなったと感じます。
Web Startは、ScalaやClojureなどのランタイムが他に必要な言語にはあまりむかないのかなと感じました。
プログラム+ライブラリ+ランタイムとなると、かなりファイルサイズが大きくなってしまいます。
ClojureScriptでgoog.graphics
altjs Advent Calendar 2012
5日目の記事です。
三目並べ
Cojureで三目並べの続き。
ここでは三目並べのClojureScriptによる実装について書きます。
ゲームのロジックは作ってあるのであとは描画のところを実装するだけ。
描画にはgoog.graphicsを使うことにします。
ClojureScriptはGoogle Closure Libraryで実装されており、nsでJavaScriptのライブラリをrequireすることが出来ます。
各種定数。
tic-tac-toe.game.Canvasを実装します。
main関数を定義します。
HTMLはコンパイルされたJavaScriptを読み込み、main関数を呼び出します。
これで動いてほしいところですが、cljs.core.logicがバグってるので、コンパイルされた.jsの修正が必要です。
cljs.core.logic.macros._take_STAR_のところをcljs.core.logic._take_STAR_に変更します。
masterでは直ってますが、修正版がpublishされていないのが悲しいですね。
いままでもClojureScriptについていろいろ書いてますが、やはりClojureは書いてて楽しいです。
最近はprotocolとrecordとmacroが好みです。
論理プログラミングで書いたコードがWeb上で動いているのはなかなかおもしろいと思うのですが、コンパイルされたJavaScriptのコードをみるとものすごくカオスです。
Google Closure Compilerによるアシストがあるとはいえ、ファイルサイズは比較的大きくなるので、注意です。
cljsbuildのおかげで、今回のようなJVMとWebの両方で動くようなコードが書けるので、これからClojureScriptを使う人には是非知ってもらいたいものです。
5日目の記事です。
三目並べ
Cojureで三目並べの続き。
ここでは三目並べのClojureScriptによる実装について書きます。
ゲームのロジックは作ってあるのであとは描画のところを実装するだけ。
goog.graphics
描画にはgoog.graphicsを使うことにします。
ClojureScriptはGoogle Closure Libraryで実装されており、nsでJavaScriptのライブラリをrequireすることが出来ます。
各種定数。
tic-tac-toe.game.Canvasを実装します。
main関数を定義します。
HTMLはコンパイルされたJavaScriptを読み込み、main関数を呼び出します。
これで動いてほしいところですが、cljs.core.logicがバグってるので、コンパイルされた.jsの修正が必要です。
cljs.core.logic.macros._take_STAR_のところをcljs.core.logic._take_STAR_に変更します。
masterでは直ってますが、修正版がpublishされていないのが悲しいですね。
雑感
いままでもClojureScriptについていろいろ書いてますが、やはりClojureは書いてて楽しいです。
最近はprotocolとrecordとmacroが好みです。
論理プログラミングで書いたコードがWeb上で動いているのはなかなかおもしろいと思うのですが、コンパイルされたJavaScriptのコードをみるとものすごくカオスです。
Google Closure Compilerによるアシストがあるとはいえ、ファイルサイズは比較的大きくなるので、注意です。
cljsbuildのおかげで、今回のようなJVMとWebの両方で動くようなコードが書けるので、これからClojureScriptを使う人には是非知ってもらいたいものです。
Clojureで三目並べ
Lisp Advent Calendar 2012
6日目の記事です。
三目並べ
ここでは三目並べソルバについて書きます。
三目並べ、すなわち◯×ゲームです。
小学生の頃とかやってました。
このゲームは両者が最善を尽せば必ず引分けになるゲームで、その最善手もわかりやすいので他人とやってもだいたいドローになります。
この三目並べで盤面から次の手を返すプログラムを、ClojureとClojureScriptの両方で動くように作成します。
今回は論理プログラミングでこのパズルを解きます。
最初にnamespaceですが、ClojureとClojureScriptの両方で動かす為に、多少の黒魔術があります。
;*CLJSBUILD-REMOVE*;はcljsbuildがビルド時に削除してくれるコメントです。
core.logicがclj版とcljs版で違うnamespaceを使っているのでこうなっています。
盤面で、空いているところはnilとします。
not-nil?という述語を作るために、!=を使いたいところですがcljs版に存在しないのでprojectを使います。
projectはcore.logicで使われている変数にあたるものから値を取り出します。
盤面が空いていたらコマを置く述語write。
コマが2連続で続いていたら自分であろうと相手であろうと決着します。
そのため、コマを優先して置く述語checkを定義します。
これで補助の述語の定義は終りです。
あとは愚直に盤面を検査します。
checkやwriteの順番を並べ変えると強くなったり弱くなったりします。
ここではなるべく中心にコマを置くように書いています。
盤面から次の手を返す述語が定義できました。
もう1つ、ゲームが終了したか調べる述語も定義します。
実際の使い方はこんな感じ。
敵味方の区別をつけていないので思った通りの手が返ってきていませんが、勝てないというのもつまらないのでこのままにします(手抜き)。
これらの関数を使い、ゲームのロジックを書きます。
Canvasプロトコルを実装し、play関数を各パネルをクリックした時のhandlerとして登録することで動きます。
JavaFXによる実装とgoog.graphicsによる実装を書きました。
core.logicによる論理プログラミングは慣れていないせいか、とても頭をつかいました。
完成したコードは愚直だけれど分かり易いものになりました。
こういった書き方が出来ることが論理プログラミングの1つの利点でもあると思います。
ゲームのロジックに関してはあまり綺麗に書けなかったのですが、各ライブラリと協調できるうまい書き方を知りたいものです。
6日目の記事です。
三目並べ
ここでは三目並べソルバについて書きます。
tic tac toe
三目並べ、すなわち◯×ゲームです。
小学生の頃とかやってました。
このゲームは両者が最善を尽せば必ず引分けになるゲームで、その最善手もわかりやすいので他人とやってもだいたいドローになります。
この三目並べで盤面から次の手を返すプログラムを、ClojureとClojureScriptの両方で動くように作成します。
core.logic
今回は論理プログラミングでこのパズルを解きます。
最初にnamespaceですが、ClojureとClojureScriptの両方で動かす為に、多少の黒魔術があります。
;*CLJSBUILD-REMOVE*;はcljsbuildがビルド時に削除してくれるコメントです。
core.logicがclj版とcljs版で違うnamespaceを使っているのでこうなっています。
盤面で、空いているところはnilとします。
not-nil?という述語を作るために、!=を使いたいところですがcljs版に存在しないのでprojectを使います。
projectはcore.logicで使われている変数にあたるものから値を取り出します。
盤面が空いていたらコマを置く述語write。
コマが2連続で続いていたら自分であろうと相手であろうと決着します。
そのため、コマを優先して置く述語checkを定義します。
これで補助の述語の定義は終りです。
あとは愚直に盤面を検査します。
checkやwriteの順番を並べ変えると強くなったり弱くなったりします。
ここではなるべく中心にコマを置くように書いています。
盤面から次の手を返す述語が定義できました。
もう1つ、ゲームが終了したか調べる述語も定義します。
実際の使い方はこんな感じ。
敵味方の区別をつけていないので思った通りの手が返ってきていませんが、勝てないというのもつまらないのでこのままにします(手抜き)。
これらの関数を使い、ゲームのロジックを書きます。
Canvasプロトコルを実装し、play関数を各パネルをクリックした時のhandlerとして登録することで動きます。
JavaFXによる実装とgoog.graphicsによる実装を書きました。
雑感
core.logicによる論理プログラミングは慣れていないせいか、とても頭をつかいました。
完成したコードは愚直だけれど分かり易いものになりました。
こういった書き方が出来ることが論理プログラミングの1つの利点でもあると思います。
ゲームのロジックに関してはあまり綺麗に書けなかったのですが、各ライブラリと協調できるうまい書き方を知りたいものです。
2012年10月31日水曜日
ClojureでLisp評価器
SICP読書会、毎週月曜19時からmixiでやってます。
現在第4章の超循環評価器を作っています。
4章の一番最初に出てくるevalの定義は以下の通り
とてもわかりやすいけど、データ主導にしたいよね、そうしよう、というのが問題4.3にあります。
これをClojureっぽく書くことを考えてみる。
ClojureといったらやっぱProtocolだよね!ということでプロトコルベースで考える。
とりあえず評価器プロトコル、Eval(uator)の定義
このプロトコルを実装したリテラルの評価器を書いてみる。
部分関数っぽくしたいのだけど、例外を投げるか迷った。
今回はとりあえずこれで。
このように、小さな評価器をいっぱい作って合成していくという考え方。
ifやdefineやbeginなんかのspecial formをチェックする関数tagged?の定義
先頭要素を比較するだけ。
これを使って、special formを以下のように表してみる
Specialを使ったquote
ifは式を評価しなければいけない。
しかし、どの評価器を使えばいいのかわからない。
評価器を引数にとるという選択肢もあるけど、不都合がある。
この式を評価するとよくわからないエラーが投げられると思う。
ここでは評価機が部分適用されたeval関数をとることにする。
一番大事な評価器を合成する関数
やっていることは簡単、引数の先頭の評価器から順に、式を評価器で評価して失敗したら次の評価器で評価するという評価器を作っているだけ。
これを使ってifとliteralだけが使えるlispを定義すると以下のようになる。
実行
ヤッター
こんな感じで小さな評価器を書いていって大きな評価器を作っています。
なかなか楽しい。
今回のプログラムはScalaBaseで@maeda_さんが発表されていた、Javascript as an Embedded DSLに触発されて書いてみました。
おもしろいので読んでみるとよいです。
次はぱーさーこんびねーたについて書く、書きたい、書けたらいいな。
現在第4章の超循環評価器を作っています。
4章の一番最初に出てくるevalの定義は以下の通り
とてもわかりやすいけど、データ主導にしたいよね、そうしよう、というのが問題4.3にあります。
これをClojureっぽく書くことを考えてみる。
Protocol
ClojureといったらやっぱProtocolだよね!ということでプロトコルベースで考える。
とりあえず評価器プロトコル、Eval(uator)の定義
このプロトコルを実装したリテラルの評価器を書いてみる。
部分関数っぽくしたいのだけど、例外を投げるか迷った。
今回はとりあえずこれで。
このように、小さな評価器をいっぱい作って合成していくという考え方。
special form
ifやdefineやbeginなんかのspecial formをチェックする関数tagged?の定義
先頭要素を比較するだけ。
これを使って、special formを以下のように表してみる
Specialを使ったquote
if
ifは式を評価しなければいけない。
しかし、どの評価器を使えばいいのかわからない。
評価器を引数にとるという選択肢もあるけど、不都合がある。
この式を評価するとよくわからないエラーが投げられると思う。
ここでは評価機が部分適用されたeval関数をとることにする。
compose
一番大事な評価器を合成する関数
やっていることは簡単、引数の先頭の評価器から順に、式を評価器で評価して失敗したら次の評価器で評価するという評価器を作っているだけ。
これを使ってifとliteralだけが使えるlispを定義すると以下のようになる。
実行
ヤッター
まとめ
こんな感じで小さな評価器を書いていって大きな評価器を作っています。
なかなか楽しい。
今回のプログラムはScalaBaseで@maeda_さんが発表されていた、Javascript as an Embedded DSLに触発されて書いてみました。
おもしろいので読んでみるとよいです。
次はぱーさーこんびねーたについて書く、書きたい、書けたらいいな。
2012年10月27日土曜日
Clojureのエラー処理
Clojureでエラー値を返すかもしれない関数ってどう書くのだろうとちょっと考えてみる。
Scalaだと例外はあまり使わず、EitherやValidationを使う派。
やはり、コンパイラの恩恵を受けることが出来る書き方が良い。
しかし、Clojureは動的型付けの言語。
コンパイラの恩恵は特にない。
なので、 どのような値が返ると扱いやすいかを考える。
Clojureは基本的に
Clojure標準のライブラリはnilを渡してもそれなりに動作するし、if-let,when-let,fnilなどの関数も用意されている。
しかし、nilだとどのようなエラーだったのか判別がつかない。
このような時に例外を使って、エラーの種類によって投げる例外を変えれば良いのだと思う。
Clojureの例外を投げるような関数は以下のように書ける。
この場合は、Java APIのIllegalArgumentExceptionとIndexOutOfBoundsExceptionを使った。
しかし、何時でもJava APIに自分が欲しいExceptionが定義されているわけではない。
このような時は、独自の例外を作るだろう。
駄菓子菓子!
Clojureでclassを定義するのはとても面倒。
nsやgen-classを見てもらえればわかると思う。
Throwableがinterfaceならば、deftypeやdefrecordが使えたのだけれど・・・
例外を定義する部分だけJavaで書いたほうが楽かも。
leiningenはJavaもサポートしているので、共存させるのは苦ではない。
基本的にnilを返す。
独自の例外を定義したかったらJavaを使うと楽
Scalaだと例外はあまり使わず、EitherやValidationを使う派。
やはり、コンパイラの恩恵を受けることが出来る書き方が良い。
しかし、Clojureは動的型付けの言語。
コンパイラの恩恵は特にない。
なので、 どのような値が返ると扱いやすいかを考える。
Clojureは基本的に
- nil返す
- 例外投げる
Clojure標準のライブラリはnilを渡してもそれなりに動作するし、if-let,when-let,fnilなどの関数も用意されている。
しかし、nilだとどのようなエラーだったのか判別がつかない。
このような時に例外を使って、エラーの種類によって投げる例外を変えれば良いのだと思う。
Clojureの例外を投げるような関数は以下のように書ける。
この場合は、Java APIのIllegalArgumentExceptionとIndexOutOfBoundsExceptionを使った。
しかし、何時でもJava APIに自分が欲しいExceptionが定義されているわけではない。
このような時は、独自の例外を作るだろう。
駄菓子菓子!
Clojureでclassを定義するのはとても面倒。
nsやgen-classを見てもらえればわかると思う。
Throwableがinterfaceならば、deftypeやdefrecordが使えたのだけれど・・・
例外を定義する部分だけJavaで書いたほうが楽かも。
leiningenはJavaもサポートしているので、共存させるのは苦ではない。
結論
基本的にnilを返す。
独自の例外を定義したかったらJavaを使うと楽
2012年10月13日土曜日
Clojureでモナド内包表記とStateモナド
cljsbuildのcrossoversという機能を知らない所為で今まで無駄に苦労してきましたが、これでマクロが使えないという制約から解き放たれました。
万歳!cljsbuild!
マクロが使えるようになってまず一番最初にやることは何か?
もちろん、モナド内包表記の実現ですね!
HaskellのdoよりはScalaのforの方が慣れているのでこちらを採用しました。
動的型付けの言語でのモナドの実現はいくつか見てきましたが、明示的にコンテキストを指定するタイプはあまり好かないので、ClojureらしくProtocolで表現することにしました。
通常モナドはunitとbindが実装され、モナド則
このインターフェースが実装されていれば、モナド内包表記が使えるようになります。
とてもScala的。
Lispは神の言語と皆ネタにしていますが、Lispのマクロは本当に強力です。
既存の言語にある構文の全てはLispのマクロで表現できるのではと思えるくらいです。
Clojureの標準ライブラリではパターンマッチが出来ないので、準標準ライブラリであるcontribのcore.matchを使います。
しんぷるいずべすと、MonadPlusなんて知らないのでガードは実装しません。めんどい。
このdo-mマクロがどのように展開してくれるかというと
が
こんな感じになります。
実際に動かしてみます。
動いたー!
素敵です。
私が現在製作中のアプリケーションでは、レコードを更新する関数が多数定義されています。
これは、状態をとって、新しい状態を返す関数ですが、少し問題があります。
一つ例を示します。
このような関数が定義されていた時、右下へ移動する関数を定義するのに->>マクロを使い、手続き的に書くことができます。
しかし、このrightでの計算結果、つまりxを使う関数を定義する時、コードはこのようになります。
このパターンが関数内で頻出する場合、一時的なcursorの状態を保存する為の変数が増えてしまいます。
さらに、この場合はxを取得するコストは微々たるものですが、フィールドの取得に複雑なロジックを用いたり、計算値が状態の更新に間接的に使われるだけで、レコードからは取得できない場合があります。
新しい状態だけを返すのではなく、計算値とのペアで返せばこのパターンを解決できます。
しかし、->>マクロのようにネストせずに書けるわけではありません。
そこでStateモナドの出番です!(導入長い!
Stateモナドは状態を取り、新しい状態と計算値のペアで返す関数に対してモナドを定義したものです。
先ほど定義したMonadicをStateに実装してみます。
right, down関数をStateで定義してみます。
この時、square関数はdo-mを使って以下のように定義できます。
ヤッター!
関数の合成が手続き的に書けますね。
マクロ強力。Stateモナド美しい。
本当はFreeモナド使おうと思ったけどStateモナドの素晴らしさを伝えたかったので控えました。
これから70個近い関数をStaeモナドに書き換える作業が待ってます。
Freeモナドの資料も作らなきゃですね。
私の代わりに大学のC言語の課題をやってくれるといいと思います。
万歳!cljsbuild!
マクロが使えるようになってまず一番最初にやることは何か?
もちろん、モナド内包表記の実現ですね!
HaskellのdoよりはScalaのforの方が慣れているのでこちらを採用しました。
動的型付けの言語でのモナドの実現はいくつか見てきましたが、明示的にコンテキストを指定するタイプはあまり好かないので、ClojureらしくProtocolで表現することにしました。
Monadic Protocol
通常モナドはunitとbindが実装され、モナド則
- bind f (unit x) == f x
- bind unit m == m
- あともう一個なんかあった気がする
このインターフェースが実装されていれば、モナド内包表記が使えるようになります。
とてもScala的。
モナド内包表記
Lispは神の言語と皆ネタにしていますが、Lispのマクロは本当に強力です。
既存の言語にある構文の全てはLispのマクロで表現できるのではと思えるくらいです。
Clojureの標準ライブラリではパターンマッチが出来ないので、準標準ライブラリであるcontribのcore.matchを使います。
しんぷるいずべすと、MonadPlusなんて知らないのでガードは実装しません。めんどい。
このdo-mマクロがどのように展開してくれるかというと
が
こんな感じになります。
実際に動かしてみます。
動いたー!
素敵です。
Stateモナド
私が現在製作中のアプリケーションでは、レコードを更新する関数が多数定義されています。
これは、状態をとって、新しい状態を返す関数ですが、少し問題があります。
一つ例を示します。
このような関数が定義されていた時、右下へ移動する関数を定義するのに->>マクロを使い、手続き的に書くことができます。
しかし、このrightでの計算結果、つまりxを使う関数を定義する時、コードはこのようになります。
このパターンが関数内で頻出する場合、一時的なcursorの状態を保存する為の変数が増えてしまいます。
さらに、この場合はxを取得するコストは微々たるものですが、フィールドの取得に複雑なロジックを用いたり、計算値が状態の更新に間接的に使われるだけで、レコードからは取得できない場合があります。
新しい状態だけを返すのではなく、計算値とのペアで返せばこのパターンを解決できます。
しかし、->>マクロのようにネストせずに書けるわけではありません。
そこでStateモナドの出番です!(導入長い!
Stateモナドは状態を取り、新しい状態と計算値のペアで返す関数に対してモナドを定義したものです。
先ほど定義したMonadicをStateに実装してみます。
right, down関数をStateで定義してみます。
この時、square関数はdo-mを使って以下のように定義できます。
ヤッター!
関数の合成が手続き的に書けますね。
まとめ
マクロ強力。Stateモナド美しい。
本当はFreeモナド使おうと思ったけどStateモナドの素晴らしさを伝えたかったので控えました。
これから70個近い関数をStaeモナドに書き換える作業が待ってます。
Freeモナドの資料も作らなきゃですね。
私の代わりに大学のC言語の課題をやってくれるといいと思います。
2012年10月3日水曜日
Clojureへの不満とか
最近はClojureばかり書いているので、良い所ばかりでなく、気になるところも見えてきました。
なにか意見をもらえるかもしれないので書き並べておきます。
Clojureのソースコードを読むときに、高確率でJavaのコードを読まなければいけないので悲しくなります。
やはり、gen-classとかでは物足りないのかなあ?
それとも、セルフホスティングにはあまりヤル気がないのか・・・・
ソースコード追うのが面倒なので。
自分で新しいデータ型を作った時に、既存の関数を使うためにclojure.langの得体の知れないinterfaceを実装するわけですが、Protocolとして存在すればClojureの中で完結するのでうれしいのだけど、これはデータ型がJavaに依存しすぎてて簡単にはいかないんだろうなあと。
特にStringとか。
charのシーケンスで返ってくるのが悲しい。
これはなぜだろう、効率のためかな?
どこかで読んだ気がしなくもない。
いっそのことClojure独自に文字列作るというのは・・・・まあ、それはそれで面倒臭そう。
Scalazは独自にCordというデータ型を定義しています。
さすが、尖ってる。
ArrayListやLinkedListを使えばいいのですが、functionalでpurelyなdata structureが欲しいわけです。
Haskellのfirst,secondに当たるものが欲しい。
分配束縛したくない。
もっとポイントフリーなプログラミングがしたいのです。
しかし、compとpartialとjuxtでやりすぎたコードを書くのには注意です。
なぜ複数束縛できないのか・・・・・
要素を1つだけ持つlistとmapとmapcatまたはforを使って、Maybeモナドっぽいことは出来ます。
あとは(fn [a] (if (nil? a) (list) (list a)))のようなものがあるといいのだけど。
for内包はあることにはあります。
しかし、これはSequableでSequentialなデータ型(JavaのIterableとIteratorのようなもの?)の為のもので、モナドの為のマクロではないです。
Maybeモナドやdo記法はalgo.monadsで提供されていますが、あまり設計に納得がいかない。
私はあるデータ型に対してモナドを定義したいので、Protocolをベースに設計したものが欲しかった。
do記法がないなら限定継続を使えばいいじゃないと昔の貴族は言ったものです。
限定継続があれば括弧を減らせるような構文がいろいろと簡単に定義できそうだなあと思い挙げてみた。
delimicといものがあるらしい。
私はいままではScalaばかり書いていましたが、いまはClojureばかり書いているのでこのような記事を書いています。
実際には2年前くらいから少しずつ書いていましたが、これほどClojureを書いてる期間はありませんでした。
Scalaに触れ、さらにScalazに触れたことで完全に関数型プログラミング信者になってしまいましたが、実際に有用な技法を多く知ることが出来ました。
それをClojureで実現するために、このような贅沢な不満が出てきました。
Clojureはまだまだ若い言語だと思うので、あれもこれもと求め過ぎていると思います。
なので、今後私が期待しているものに発展してくれるようClojureに貢献していきたいです。
なにか意見をもらえるかもしれないので書き並べておきます。
セルフホスティングして欲しい
Clojureのソースコードを読むときに、高確率でJavaのコードを読まなければいけないので悲しくなります。
やはり、gen-classとかでは物足りないのかなあ?
それとも、セルフホスティングにはあまりヤル気がないのか・・・・
clojure.langのJavaDoc欲しい
ソースコード追うのが面倒なので。
Protocolをもっと使って欲しい
自分で新しいデータ型を作った時に、既存の関数を使うためにclojure.langの得体の知れないinterfaceを実装するわけですが、Protocolとして存在すればClojureの中で完結するのでうれしいのだけど、これはデータ型がJavaに依存しすぎてて簡単にはいかないんだろうなあと。
関数が返す値は適用する値と同じデータ型で返して欲しい
特にStringとか。
charのシーケンスで返ってくるのが悲しい。
これはなぜだろう、効率のためかな?
どこかで読んだ気がしなくもない。
いっそのことClojure独自に文字列作るというのは・・・・まあ、それはそれで面倒臭そう。
Scalazは独自にCordというデータ型を定義しています。
さすが、尖ってる。
insertしたい
ArrayListやLinkedListを使えばいいのですが、functionalでpurelyなdata structureが欲しいわけです。
Arrowが欲しい
Haskellのfirst,secondに当たるものが欲しい。
分配束縛したくない。
もっとポイントフリーなプログラミングがしたいのです。
しかし、compとpartialとjuxtでやりすぎたコードを書くのには注意です。
if-let, when-letが1つの変数しか束縛できない
なぜ複数束縛できないのか・・・・・
要素を1つだけ持つlistとmapとmapcatまたはforを使って、Maybeモナドっぽいことは出来ます。
あとは(fn [a] (if (nil? a) (list) (list a)))のようなものがあるといいのだけど。
do記法、for内包、コンピュテーション式にあたるものが欲しい
for内包はあることにはあります。
しかし、これはSequableでSequentialなデータ型(JavaのIterableとIteratorのようなもの?)の為のもので、モナドの為のマクロではないです。
Maybeモナドやdo記法はalgo.monadsで提供されていますが、あまり設計に納得がいかない。
私はあるデータ型に対してモナドを定義したいので、Protocolをベースに設計したものが欲しかった。
限定継続が欲しい
do記法がないなら限定継続を使えばいいじゃないと昔の貴族は言ったものです。
限定継続があれば括弧を減らせるような構文がいろいろと簡単に定義できそうだなあと思い挙げてみた。
delimicといものがあるらしい。
まとめ
私はいままではScalaばかり書いていましたが、いまはClojureばかり書いているのでこのような記事を書いています。
実際には2年前くらいから少しずつ書いていましたが、これほどClojureを書いてる期間はありませんでした。
Scalaに触れ、さらにScalazに触れたことで完全に関数型プログラミング信者になってしまいましたが、実際に有用な技法を多く知ることが出来ました。
それをClojureで実現するために、このような贅沢な不満が出てきました。
Clojureはまだまだ若い言語だと思うので、あれもこれもと求め過ぎていると思います。
なので、今後私が期待しているものに発展してくれるようClojureに貢献していきたいです。
2012年9月13日木曜日
ClojureScriptのテスト
皆さんテスト書いてますか?
私はあまり書いてません。
テストは大事です、書きましょう。
私は現在ClojureScriptを使っているのですが、JavaScriptでのテスト方法とかよくわからないし、Clojureでテスト書きたいので、ClojureからClojureScriptを読み込もうという考えに至りました。
が、しかし。
requireなどを使って、ClojureScriptのコードを読み込むことはできませんでした。
なぜなら拡張子がcljsだから。
load-fileなども使ってみましたが、無理でした。
ClojureScriptのコードの中でrequireを使っているからです。
どうにかして拡張子がclj,classのファイル以外を読み込むことはできないのかと調べてみたところ・・・・
https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/RT.java#L403
ベタ書き・・・!
差し替えることなど到底無理っぽい。
ならば作るしかありません、cljファイルを。
copyしてuseしてdeleteする、悲しみあふれるコード。
cleanupのところはtry-finallyした方が良いかも。
clojure.testはfailした時にマクロを利用して述語に渡した値を展開してくれたりでなかなか便利なので割と好きです。
しかし、ここまでして使うのもどうかなと。
素直にJavaScriptのテストフレームワークを使うとか、assertで済ませる(ClojureScript本体のテスト方法)などでいいかもしれません。
私はあまり書いてません。
テストは大事です、書きましょう。
私は現在ClojureScriptを使っているのですが、JavaScriptでのテスト方法とかよくわからないし、Clojureでテスト書きたいので、ClojureからClojureScriptを読み込もうという考えに至りました。
が、しかし。
requireなどを使って、ClojureScriptのコードを読み込むことはできませんでした。
なぜなら拡張子がcljsだから。
load-fileなども使ってみましたが、無理でした。
ClojureScriptのコードの中でrequireを使っているからです。
どうにかして拡張子がclj,classのファイル以外を読み込むことはできないのかと調べてみたところ・・・・
https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/RT.java#L403
ベタ書き・・・!
差し替えることなど到底無理っぽい。
ならば作るしかありません、cljファイルを。
copyしてuseしてdeleteする、悲しみあふれるコード。
cleanupのところはtry-finallyした方が良いかも。
clojure.testはfailした時にマクロを利用して述語に渡した値を展開してくれたりでなかなか便利なので割と好きです。
しかし、ここまでして使うのもどうかなと。
素直にJavaScriptのテストフレームワークを使うとか、assertで済ませる(ClojureScript本体のテスト方法)などでいいかもしれません。
2012年9月5日水曜日
Clojureのinsert
Clojureでlistやvectorのn番目に値をinsertしたい時はありませんか?
Clojureには標準でlistやvectorに対するinsertが定義されていません。
でもzipperにはinsertがあるみたい。
そこでvectorとzipper、どちらのinsertが速いか測ってみました。
ClojureScript
Clojure
思っていたよりは差がつかなかった。
vectorやlistはいつもこんな感じでinsertしてるのですが、もっと綺麗で効率のよい方法があったら教えて下さい。
効率のよいinsertが出来るシーケンスを標準で用意してくれてもいいのではと思わなくもないです。
Clojureには標準でlistやvectorに対するinsertが定義されていません。
でもzipperにはinsertがあるみたい。
そこでvectorとzipper、どちらのinsertが速いか測ってみました。
コード
結果
ClojureScript
Clojure
思っていたよりは差がつかなかった。
vectorやlistはいつもこんな感じでinsertしてるのですが、もっと綺麗で効率のよい方法があったら教えて下さい。
効率のよいinsertが出来るシーケンスを標準で用意してくれてもいいのではと思わなくもないです。
2012年8月26日日曜日
ClojureScript
最近はClojureScriptばかり書いてます。
Clojureを書いてるとJavaを意識しなければいけないことがありますが、ClojureScriptも同じでJavaScriptを意識しなければなりません。
とはいってもJavaScriptを書くよりも遥かに快適なので是非広まって欲しいものです。
今日までにClojureScriptを書いてきて、わかったことを少しまとめようと思います。
Google Closure Libraryのラッパーで、domやevent、netなどのライブラリがあります。
domとeventを触りましたが、ものすごく中途半端です。
結局goog.domやgoog.eventの関数が必要になるので、 まだまだ発展途上と言えるでしょう。
Closure Libraryの関数はJavaScriptのArrayやObjectを扱うものが多く、ClojureScriptのデータ型を渡すときに少々不便だったりします。
clojure.browserはそういった不満を解消するものとなってほしいです。
ちょっと便利な関数
JavaScriptの世界で生きていくためにはClojureの標準ライブラリの関数だけでは生きていけません。
なので、ClojureScriptにはClojureとJavaScriptの間を取り持つ関数が存在します。
しかし、ドキュメントが少なすぎて存在があまり知られていないように感じます。かなしい。
js-objとarrayは特に重要です。
それぞれObjectとArrayを生成する関数です。
主にClosure Libraryの関数を呼び出す為に使います。
js-keysやjs-deleteなんかも覚えておきましょう。
JavaScriptを直接実行するjs*なんかもありますが、最終手段とするべきでしょう。
array-seqも便利です。
JavaScriptのArray的データ型(NodeList, FileListなど)をClojureScriptのデータ型に変換するものです。
(extend-type Hoge ISeqable (-seq [hoge] (array-seq hoge)))
としておくとClojureScriptのコレクション関連の関数が使えて便利になります。
ちゃんとClojureScriptのライブラリだって存在します。
ClojureScriptやりましょうず!
Clojureを書いてるとJavaを意識しなければいけないことがありますが、ClojureScriptも同じでJavaScriptを意識しなければなりません。
とはいってもJavaScriptを書くよりも遥かに快適なので是非広まって欲しいものです。
今日までにClojureScriptを書いてきて、わかったことを少しまとめようと思います。
clojure.browser
Google Closure Libraryのラッパーで、domやevent、netなどのライブラリがあります。
domとeventを触りましたが、ものすごく中途半端です。
結局goog.domやgoog.eventの関数が必要になるので、 まだまだ発展途上と言えるでしょう。
Closure Libraryの関数はJavaScriptのArrayやObjectを扱うものが多く、ClojureScriptのデータ型を渡すときに少々不便だったりします。
clojure.browserはそういった不満を解消するものとなってほしいです。
ちょっと便利な関数
- clojure.browser.dom/ensure-element
- keywordを渡すとgetElementとして、 stringを渡すとhtmlToDocumentFragmentとして動きます
- clojure.browser.dom/log
- Console#logです
- *print-fn*にset!するのが一般的?
ClojureとJavaScript
JavaScriptの世界で生きていくためにはClojureの標準ライブラリの関数だけでは生きていけません。
なので、ClojureScriptにはClojureとJavaScriptの間を取り持つ関数が存在します。
しかし、ドキュメントが少なすぎて存在があまり知られていないように感じます。かなしい。
js-objとarrayは特に重要です。
それぞれObjectとArrayを生成する関数です。
主にClosure Libraryの関数を呼び出す為に使います。
js-keysやjs-deleteなんかも覚えておきましょう。
JavaScriptを直接実行するjs*なんかもありますが、最終手段とするべきでしょう。
array-seqも便利です。
JavaScriptのArray的データ型(NodeList, FileListなど)をClojureScriptのデータ型に変換するものです。
(extend-type Hoge ISeqable (-seq [hoge] (array-seq hoge)))
としておくとClojureScriptのコレクション関連の関数が使えて便利になります。
外部ライブラリ
ちゃんとClojureScriptのライブラリだって存在します。
- core.match
- パターンマッチを提供してくれるライブラリ、便利。
- core.logic
- JavaScriptで論理プログラミングが出来るよ!やったね!
- しかしバグあるしあまり期待しないほうがいい。
読まなければいけないもの
- https://github.com/clojure/clojurescript/wiki/Differences-from-Clojure
- http://himera.herokuapp.com/synonym.html
ClojureScriptやりましょうず!
2012年7月2日月曜日
core.logic
clojureのcontribをながめてるとcore.logicなるものが。
なにやらClojureで論理プログラミングをするためのものらしいのでいろいろと試してみた。
よく例に出るappendの例。
xとyが連結するリスト、zが連結後のリストです。
xが空ならyとzは同じ。
xの先頭とzの先頭が同じなら、xのテールとyを連結したzのテールになる。
普通の関数で書いたらこんな感じ?
しかし、普通の関数と違ってかなり高機能です。
実行してみます。
なんと、append一つ定義するだけで連結・差分・組み合わせの三つの使い方が出来るのです!
おー、論理プログラミングすげー
さらに、ClojureScript版も用意されています。
上記のappendのコードは動きますが、clojure.core.logicと比べると定義されている関数やマクロは少ないです。
バグってたりします。
数独も解いてみた。
数字の扱いが微妙なのでリストで数字を表してみました。
しかしこのコード、正しいパズルかどうかはテストしてくれますが、パズルを解決してくれません。
!=を使っているから・・・・?
まあ、まだまだ開発途中なので今後に期待です。
なにやらClojureで論理プログラミングをするためのものらしいのでいろいろと試してみた。
よく例に出るappendの例。
xとyが連結するリスト、zが連結後のリストです。
xが空ならyとzは同じ。
xの先頭とzの先頭が同じなら、xのテールとyを連結したzのテールになる。
普通の関数で書いたらこんな感じ?
しかし、普通の関数と違ってかなり高機能です。
実行してみます。
なんと、append一つ定義するだけで連結・差分・組み合わせの三つの使い方が出来るのです!
おー、論理プログラミングすげー
さらに、ClojureScript版も用意されています。
上記のappendのコードは動きますが、clojure.core.logicと比べると定義されている関数やマクロは少ないです。
バグってたりします。
数独も解いてみた。
数字の扱いが微妙なのでリストで数字を表してみました。
しかしこのコード、正しいパズルかどうかはテストしてくれますが、パズルを解決してくれません。
!=を使っているから・・・・?
まあ、まだまだ開発途中なので今後に期待です。
2012年4月21日土曜日
ClojureScriptの導入
ハードル高いと言われてしまったので。
まずはbuild toolの導入です。
https://github.com/technomancy/leiningen
からスクリプトをダウンロードしましょう。
ターミナルを立ち上げて
が実行出来ればleiningenの導入は完了です。
ターミナルで
と打ちましょう。
cljstestというプロジェクトが作られます。
作られたプロジェクトのディレクトリには、project.cljが存在します。
これを以下のように書き換えて下さい。
詳しい設定の仕方は
https://github.com/emezeske/lein-cljsbuild
編集ができたら
を実行して下さい。
cljstest/src/cljstestに存在するcore.cljをcore.cljsにリネームし、以下のように編集します。
ファイルを保存すると自動でコンパイルされ、 cljstestにmain.jsが作成されます。
以下のようなhtmlファイルをcljstestに作り、実行してみましょう。
アラートが出れば完成です。
Leiningenの導入
まずはbuild toolの導入です。
https://github.com/technomancy/leiningen
からスクリプトをダウンロードしましょう。
- Linux
- Installationの"Download the script"
- Windows
- Installationの"the batch file"
ターミナルを立ち上げて
lein self-install
が実行出来ればleiningenの導入は完了です。
Projectの作成
ターミナルで
lein new cljstest
と打ちましょう。
cljstestというプロジェクトが作られます。
作られたプロジェクトのディレクトリには、project.cljが存在します。
これを以下のように書き換えて下さい。
詳しい設定の仕方は
https://github.com/emezeske/lein-cljsbuild
編集ができたら
lein deps
lein cljsbuild auto
を実行して下さい。
core.cljsの編集
cljstest/src/cljstestに存在するcore.cljをcore.cljsにリネームし、以下のように編集します。
ファイルを保存すると自動でコンパイルされ、 cljstestにmain.jsが作成されます。
以下のようなhtmlファイルをcljstestに作り、実行してみましょう。
アラートが出れば完成です。
2012年4月16日月曜日
ClojureScript
最近うぇっぶの勉強が足りないと思い、なんか書いてます。
せっかくだから新しいものに手を出していこうと思い、いろいろと挑戦しています。
使っている言語、ライブラリは
便利なライブラリに驚きつつも、覚えなければいけないことが多くてなかなか大変です。
この中でも特に嵌ったものがClojureScript(Closure Library)。
情報が少ないので調べるのにも結構苦労します。
ClojureScript自体はとてもいいものなので、普及のため/覚え書きに基本的なことを書いていきます。
なので、ClojureとClosure Libraryの両方を使えるようにならなければなりません!
学習コスト高いですね。しかし、言語的に強力なClojureと強大なライブラリ群のClosure Libraryが合わさっているので最強の環境だと思うのですよ!
なので皆さん是非使って私に教えて下さい。
ClojureのデファクトなビルドツールとしてLeiningenがあります。
そして、ClojureScriptをビルドするpluginとしてlein-cljsbuildが存在します。
これなしには開発できないレベルで便利です。
是非使いましょう。
emacsを使っている人は、clojurescript-modeというものもあるので入れておくと便利だと思います。
では、実際のコードをみてポイントを書いていきたいと思います。
nsはClosure Libraryのprovideの役割を果たします。
(ns hoge)で定義された(def geso)は外部からhoge.gesoでアクセス出来ます。
嵌ります。
:asが必須です。
あとUpperCamelだからといってクラス名と勘違いしないで下さい。
あくまでこれはClojureScriptなのです。
このrequireはClosure Libraryのrequireです。
注意して下さい。
:asで付けたaliasはstatic methodチックに呼び出せます。
Clojureでは書き換え可能な参照を作るのにrefやatomを使いますが、これはJavaScriptなのでそんなことをせずにset!で直接varを書き換えることができます。
あとrefを使ってもSTMが使えるわけではないです。
windowやdocumentなどのオブジェクトにアクセスしたい時はgoog.globalを使いましょう。
JavaScript Objectのインスタンスを作りたい時もこれを使うことになると思います。
※追記
goog.globalを使わなくてもjs/Stringのようにglobal objectを参照できました。
とりあえずこんなところかな?
もっとたくさん苦労したところがあった気がする・・・・・
まあ、随時記事を書いていこうと思います。
私はClojure自体は慣れていたのですが、JavaScriptは初心者レベルだしClosure Libraryは触ったことがないしでとても大変でした。
ClojureScriptを書くとしてもJavaScriptがゆるふわなところには振り回されると思うので覚悟しておいて下さい。
せっかくだから新しいものに手を出していこうと思い、いろいろと挑戦しています。
使っている言語、ライブラリは
- Scala
- Unfiltered
- Scalate
- Jade
- CoffeeScript
- SASS
- JavaFX
- ClojureScript
- Closure Library
- Jython
- Pygments
便利なライブラリに驚きつつも、覚えなければいけないことが多くてなかなか大変です。
この中でも特に嵌ったものがClojureScript(Closure Library)。
情報が少ないので調べるのにも結構苦労します。
ClojureScript自体はとてもいいものなので、普及のため/覚え書きに基本的なことを書いていきます。
ClojureScript
ClojureScriptはGoogle Closure Libraryに依存しています!(重要)なので、ClojureとClosure Libraryの両方を使えるようにならなければなりません!
学習コスト高いですね。しかし、言語的に強力なClojureと強大なライブラリ群のClosure Libraryが合わさっているので最強の環境だと思うのですよ!
なので皆さん是非使って私に教えて下さい。
開発環境
ClojureのデファクトなビルドツールとしてLeiningenがあります。
そして、ClojureScriptをビルドするpluginとしてlein-cljsbuildが存在します。
これなしには開発できないレベルで便利です。
lein cljsbuild auto
とやっておくだけで信じられない速度でcompileしてくれます。是非使いましょう。
emacsを使っている人は、clojurescript-modeというものもあるので入れておくと便利だと思います。
cljs
では、実際のコードをみてポイントを書いていきたいと思います。
ns
nsはClosure Libraryのprovideの役割を果たします。
(ns hoge)で定義された(def geso)は外部からhoge.gesoでアクセス出来ます。
:require
嵌ります。
:asが必須です。
あとUpperCamelだからといってクラス名と勘違いしないで下さい。
あくまでこれはClojureScriptなのです。
このrequireはClosure Libraryのrequireです。
注意して下さい。
:asで付けたaliasはstatic methodチックに呼び出せます。
参照
Clojureでは書き換え可能な参照を作るのにrefやatomを使いますが、これはJavaScriptなのでそんなことをせずにset!で直接varを書き換えることができます。
あとrefを使ってもSTMが使えるわけではないです。
goog.global
windowやdocumentなどのオブジェクトにアクセスしたい時はgoog.globalを使いましょう。
JavaScript Objectのインスタンスを作りたい時もこれを使うことになると思います。
※追記
goog.globalを使わなくてもjs/Stringのようにglobal objectを参照できました。
総括
とりあえずこんなところかな?
もっとたくさん苦労したところがあった気がする・・・・・
まあ、随時記事を書いていこうと思います。
私はClojure自体は慣れていたのですが、JavaScriptは初心者レベルだしClosure Libraryは触ったことがないしでとても大変でした。
ClojureScriptを書くとしてもJavaScriptがゆるふわなところには振り回されると思うので覚悟しておいて下さい。
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で動くので、是非試してみて下さい。
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で動くので、是非試してみて下さい。
登録:
投稿 (Atom)



