跡地です。引っ越しました。http://d.hatena.ne.jp/nosen
N2 ToolBox(跡地)
引っ越しました
思うところあって、Blogを引っ越すことにしました。
引っ越し先はコチラ↓
http://d.hatena.ne.jp/nosen/
今後もまとまった量なにか書きたいことがあったら更新していきますので、
よかったらのぞいてみてくださいね。
引っ越し先はコチラ↓
http://d.hatena.ne.jp/nosen/
今後もまとまった量なにか書きたいことがあったら更新していきますので、
よかったらのぞいてみてくださいね。
Scalaコピペ道場:java.io.Fileのラッパを作ってみた
ほんの思いつき、かつ ほかに誰かが既にやってそうですけど、作ってみました。
java.io.Fileのラッパです。
使い方はこんな感じ。
1 import io.File._
2 import io.IO
3
4 //カレントディレクトリ直下のsrcディレクトリ以下の
5 //.scalaファイルを再帰的に検索
6 val src = pwd / "src"
7 val scalaFiles = find(src).filter(_.getName.endsWith(".scala"))
8 for(f <- scalaFiles) {
9 println(f.getName)
10 }
11
12 //見つけたScalaファイルを標準出力に出力
13 for(f <- scalaFiles) {
14 f > IO.Std
15
16 }
17
18 //ファイルのコピー
19 (pwd / "build.xml") > (pwd / "build.xml.bkp")
20
21 //build.xmlを標準出力に出力
22 (pwd / "build.xml") > IO.Std
23
"/" メソッドで子ファイルが取れるっていうのと、">"でファイルのコピーが出来るっていうがやりたかったんです。
それだけです。
でも、いろんな便利メソッドを追加していったら、もしかしたら便利かもしれない。。
ソースはこちら↓
http://hg.sourceforge.jp/view/scala-cp-src/main/file/c08b917a8886/src/main/io/File.scala
java.io.Fileのラッパです。
使い方はこんな感じ。
1 import io.File._
2 import io.IO
3
4 //カレントディレクトリ直下のsrcディレクトリ以下の
5 //.scalaファイルを再帰的に検索
6 val src = pwd / "src"
7 val scalaFiles = find(src).filter(_.getName.endsWith(".scala"))
8 for(f <- scalaFiles) {
9 println(f.getName)
10 }
11
12 //見つけたScalaファイルを標準出力に出力
13 for(f <- scalaFiles) {
14 f > IO.Std
15
16 }
17
18 //ファイルのコピー
19 (pwd / "build.xml") > (pwd / "build.xml.bkp")
20
21 //build.xmlを標準出力に出力
22 (pwd / "build.xml") > IO.Std
23
"/" メソッドで子ファイルが取れるっていうのと、">"でファイルのコピーが出来るっていうがやりたかったんです。
それだけです。
でも、いろんな便利メソッドを追加していったら、もしかしたら便利かもしれない。。
ソースはこちら↓
http://hg.sourceforge.jp/view/scala-cp-src/main/file/c08b917a8886/src/main/io/File.scala
Ivyで複数のMavenリポジトリを使う
最近個人的にivyを使ってみてます。
Mavenよりは若干取っ付きにくいですが、慣れてくると自由が利いていいのかもしれません。
まだ慣れてないので、なんとも言えないのですが。。
さて、以下の設定はScalaTestとか、ibiblioでない独自のリポジトリを持っているライブラリを取ってくるために、
複数のMavenリポジトリを使うようにする、ivy-settings.xmlの設定例です。
自分用メモです。
1 <ivysettings>
2 <settings defaultResolver="default"/>
3 <resolvers>
4 <ibiblio name="ibiblio" m2compatible="true"/>
5 <url name="scala-tools" m2compatible="true">
6 <artifact pattern="http://scala-tools.org/repo-releases/[organisation]/[module]/[revision]/[artifact]-[revision].[ext]"/>
7 </url>
8 <chain name="public" returnFirst="true">
9 <resolver ref="scala-tools"/>
10 <resolver ref="ibiblio"/>
11 </chain>
12 </resolvers>
13 <include url="${ivy.default.settings.dir}/ivysettings-shared.xml"/>
14 <include url="${ivy.default.settings.dir}/ivysettings-local.xml"/>
15 <include url="${ivy.default.settings.dir}/ivysettings-main-chain.xml"/>
16 <include url="${ivy.default.settings.dir}/ivysettings-default-chain.xml"/>
17 </ivysettings>
Mavenよりは若干取っ付きにくいですが、慣れてくると自由が利いていいのかもしれません。
まだ慣れてないので、なんとも言えないのですが。。
さて、以下の設定はScalaTestとか、ibiblioでない独自のリポジトリを持っているライブラリを取ってくるために、
複数のMavenリポジトリを使うようにする、ivy-settings.xmlの設定例です。
自分用メモです。
1 <ivysettings>
2 <settings defaultResolver="default"/>
3 <resolvers>
4 <ibiblio name="ibiblio" m2compatible="true"/>
5 <url name="scala-tools" m2compatible="true">
6 <artifact pattern="http://scala-tools.org/repo-releases/[organisation]/[module]/[revision]/[artifact]-[revision].[ext]"/>
7 </url>
8 <chain name="public" returnFirst="true">
9 <resolver ref="scala-tools"/>
10 <resolver ref="ibiblio"/>
11 </chain>
12 </resolvers>
13 <include url="${ivy.default.settings.dir}/ivysettings-shared.xml"/>
14 <include url="${ivy.default.settings.dir}/ivysettings-local.xml"/>
15 <include url="${ivy.default.settings.dir}/ivysettings-main-chain.xml"/>
16 <include url="${ivy.default.settings.dir}/ivysettings-default-chain.xml"/>
17 </ivysettings>
Scalaコピペ道場
ScalaのDIフレームワーク、改善しているうちにBlogに貼付けられる長さではなくなってきたので、
SourceForge にプロジェクトを作ってそこにコミットすることにしました。
ソースがこれで↓
http://hg.sourceforge.jp/view/scala-cp-src/main/file/3154e54d94e6/src/main/inject/Component.scala
仕様はこれ↓
http://hg.sourceforge.jp/view/scala-cp-src/main/file/3154e54d94e6/src/test/inject/ComponentSpec.scala
現在87行。。前回はまった共変の罠 問題は解決されています。
このSourceForgeのプロジェクトは、今回のように
Jarにして配布するまでもないけど、そこそこ再利用性のありそうなコードをコピペベースで利用して
もらうために配布するプロジェクト、というふれこみになっています。
名づけて
「Scalaコピペ道場」
まだ自分はScala修行中なので、「道場」ってつけてみました。
今後もよさげなコードがかけたら追加していきたいと思います。
ソースツリーごとチェックアウトしたい人は、Mercurialで
hg clone http://hg.sourceforge.jp/view/scala-cp-src/main/
で落とせます。
SourceForge にプロジェクトを作ってそこにコミットすることにしました。
ソースがこれで↓
http://hg.sourceforge.jp/view/scala-cp-src/main/file/3154e54d94e6/src/main/inject/Component.scala
仕様はこれ↓
http://hg.sourceforge.jp/view/scala-cp-src/main/file/3154e54d94e6/src/test/inject/ComponentSpec.scala
現在87行。。前回はまった共変の罠 問題は解決されています。
このSourceForgeのプロジェクトは、今回のように
Jarにして配布するまでもないけど、そこそこ再利用性のありそうなコードをコピペベースで利用して
もらうために配布するプロジェクト、というふれこみになっています。
名づけて
「Scalaコピペ道場」
まだ自分はScala修行中なので、「道場」ってつけてみました。
今後もよさげなコードがかけたら追加していきたいと思います。
ソースツリーごとチェックアウトしたい人は、Mercurialで
hg clone http://hg.sourceforge.jp/view/scala-cp-src/main/
で落とせます。
共変の罠
前回のエントリで
こんな感じのサンプルを示したのですが、実は、これ、意図した通りに
コンパイラの型のチェックがかからないことが判明してしまいました。
これでもコンパイルが通ってしまうのです。第一引数がKey[B]なら第二引数は(Injector)=>B
でないとエラーになるようにしたかったのに。。
このとき、defineメソッドのシグネチャがどんな風になっているのかというと、
こんなふうになっていました。
問題はdefineの呼び出し時に明示的に型パラメータを指定していないことでした。
こうやって、型を明示的に指定してあげると、ちゃんとコンパイルエラーになります。
おそらく、型を指定しないと、このケースでは戻り値の型から型推論することができないので、
コンパイラは
こういう風に解釈しているのだと思われます。
そして、KeyもFunctionもTに関して共変な型であったがためにこれで
普通にコンパイル通ってしまっていたのかと。
Javaには共変、反変という概念がないので、こういうはまり方はScalaならではといえます。
いちいち型パラメータを明示的に指定しないといけない上に、
指定しないと中途半端にコンパイルが通ってしまうというのはよろしくないので、
対策を考えたいと思います。
object A extends Key[A]
class A {
def methodA = "a"
}
object B extends Key[B]
class B(inject:Injector) {
val a = inject(A)
}
val component = Component.define(B, new B(_))
.define(A, new A)
val b = component(B)
こんな感じのサンプルを示したのですが、実は、これ、意図した通りに
コンパイラの型のチェックがかからないことが判明してしまいました。
val component = Component.define(B, new B(_))
.define(B, new A) //本当はエラー
これでもコンパイルが通ってしまうのです。第一引数がKey[B]なら第二引数は(Injector)=>B
でないとエラーになるようにしたかったのに。。
このとき、defineメソッドのシグネチャがどんな風になっているのかというと、
def define[T](key:Key[T], factory: (Injector)=> T) def define[T](key:Key[T], factory: => T)
こんなふうになっていました。
問題はdefineの呼び出し時に明示的に型パラメータを指定していないことでした。
val component = Component.define[B](B, new B(_))
.define[A](B, new A) //コンパイルエラーになる
こうやって、型を明示的に指定してあげると、ちゃんとコンパイルエラーになります。
おそらく、型を指定しないと、このケースでは戻り値の型から型推論することができないので、
コンパイラは
val component = Component.define[Any](B, new B(_))
.define[Any](B, new A)
こういう風に解釈しているのだと思われます。
そして、KeyもFunctionもTに関して共変な型であったがためにこれで
普通にコンパイル通ってしまっていたのかと。
Javaには共変、反変という概念がないので、こういうはまり方はScalaならではといえます。
いちいち型パラメータを明示的に指定しないといけない上に、
指定しないと中途半端にコンパイルが通ってしまうというのはよろしくないので、
対策を考えたいと思います。
| « 前ページ |

