N2 ToolBox(跡地)

跡地です。引っ越しました。http://d.hatena.ne.jp/nosen

引っ越しました

2010-05-04 17:32:46 | その他
思うところあって、Blogを引っ越すことにしました。

引っ越し先はコチラ↓

http://d.hatena.ne.jp/nosen/

今後もまとまった量なにか書きたいことがあったら更新していきますので、
よかったらのぞいてみてくださいね。

Scalaコピペ道場:java.io.Fileのラッパを作ってみた

2009-10-28 23:37:14 | 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リポジトリを使う

2009-10-26 21:18:58 | オープンソース
最近個人的に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>



Scalaコピペ道場

2009-10-22 08:07:02 | 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/

で落とせます。


共変の罠

2009-10-17 10:15:12 | 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ならではといえます。

いちいち型パラメータを明示的に指定しないといけない上に、
指定しないと中途半端にコンパイルが通ってしまうというのはよろしくないので、
対策を考えたいと思います。