2011年12月14日水曜日

Mavenでたまにchecksumエラーで依存を解決できない

最近、mavenで依存性解決しようとすると、
Checksum validation failed, no checksums available from the repository

なエラーでてライブラリを取ってこれないことがある。

レポジトリを確認してみると、本来はpomやjarとともにそのmd5やshaのハッシュ値ファイルも置かれているはずが、それらのレポジトリにはそのファイルが無くどうもそのせいでChecksumが出来ずに失敗してしまっているっぽい。最近だと例えば
org.scala-tools.testing:scalacheck_2.9.0-1:jar:1.9
とか失敗したんだけど、どうもsbt(というかivy?)でデプロイされてそうなやつっぽい。

とりあえず解決策としては、--lax-checksumsのオプションを付けてMavenを実行してやれば解決はする。

PS.ちなみにIntelliJを使っているなら、Run/Debug Configuration > General > Checksum PolicyをWarnにすれば、--lax-checksumsオプションを付けて実行してくれる。

2011年9月22日木曜日

Javaのクラスに同名、同引数のメソッドが定義される件

javaの仕様?と思われますが、ある特定の条件下でリフレクションを使用した場合、困ったことになります。

例えば、このようなクラスを定義します。

scala

trait FirstDef[T]{
def id : T
}

class Conc extends FirstDef[Long]{
def id = 23L
}


java

interfaceFirstDef{
public T id();
}

class Conc implements FirstDef{
public Long id() = 23L
}

そして、ConcクラスをReflectionにかけると・・・


> classOf[Conc].getMethods(println(_))

public long Conc.id()
public java.lang.Object Conc.id()
public final native void java.lang.Object.wait(long) th
public final void java.lang.Object.wait() throws java.l
public final void java.lang.Object.wait(long,int) throw
public boolean java.lang.Object.equals(java.lang.Object
public java.lang.String java.lang.Object.toString()
public native int java.lang.Object.hashCode()
public final native java.lang.Class java.lang.Object.ge
public final native void java.lang.Object.notify()
public final native void java.lang.Object.notifyAll()



なんと、引数なしのid()メソッドが2つ定義されてしまいます!!!
しかし、戻り値はlongとjava.lang.Object。
Reflectionをがりがり使うライブラリを使用している場合、高確率でバグが出ちゃいます。

これは、継承しているTrait(Interface)の型テンプレートを実現するためと思われ、回避不可能です。Reflectionを使用するライブラリを作る場合はこのようなことがあるということに気をつけましょう。

2011年8月5日金曜日

Githubの小技

githubでの小技紹介


便利度★★★



Sourceタブで、tキーを押すとソース検索モードになります。
Pushされているファイルの中から簡単にファイルを探し出せます。




便利度★★



Wikiに、直接MarkdownやTexitileフォーマットのファイルをPushして編集できます。
Wiki -> Git access から見れるレポジトリがWiki用のレポジトリになっています。

2011年6月1日水曜日

ScalaのOptionやListのfilterとwithFilterの違い

Option,Listには
filter
withFilter
の2種類のメソッドが存在します。
どちらも引数は
T => Boolean

でFilterの処理を行いますが、ほかのmapや多段のfilterを組み合わせる場合違いが出てきます。

以下が実際の実行結果の違いです。
どちらも、偶数だけを取り出して、2倍をしたリストを取得しています。


val l = List(1,2,3,4)

l.withFilter( i => {
println("fitler " + i)
i % 2 == 0
}).map( i => {
println("map " + i)
i * 2
})


l.filter( i => {
println("fitler " + i)
i % 2 == 0
}).map( i => {
println("map " + i)
i * 2
})



実行結果は以下のようになります。


//withFilter -> map
fitler 1
fitler 2
map 2
fitler 3
fitler 4
map 4
fitler 5

//filter -> map
fitler 1
fitler 2
fitler 3
fitler 4
fitler 5
map 2
map 4



filterを使用した場合、途中でfilterされたListが生成されてしまいますが、
withFilterを使用した場合、中間状態のListは生成されません。
もし、filterやmapを何段も使用する場合はwithFilterを使ったほうがパフォーマンスが高くなります。

2011年5月26日木曜日

Lift Mapper How To

Lift Mapperでテーブル設計をする際の最小限の知識のまとめ
詳しいことはここを見てください。
主にMySQLを使用しているため、DBの用語等はMySQLのものとなります。

よく使われるフィールド

object DefaultFieldModel extends DefaultFieldModel with LongKeyedMetaMapper[DefaultFieldModel]

class DefaultFieldModel extends LongKeyedMapper[DefaultFieldModel]{
  def getSingleton = DefaultFieldModel 

  object idField extends MappedLongIndex(this) 

  object intField extends MappedInt(this)
  object longField extends MappedLong(this)
  object varcharField extends MappedString(this,100)// VARCHAR(100)
  object textField extends MappedText(this) // TEXT
  object dateField extends MappedDate(this) // DATE
  object dateTimeField extends MappedDateTime(this) // DATETIME

}

//usage

val newObject = DefaultFieldModel.createInstance
newObject.idField(1)
newObject.textField("hoge")
...
newObject.save()


val read = DefaultFieldModel.findByKey(1L).open_!
println("ID:" + read.idField.is)




AUTO INCREMENTなIDの設定 + CRUD画面の簡単生成

object AutoIncrement extends AutoIncrement with LongKeyedMetaMapper[AutoIncrement] with CRUDify[Long,AutoIncrement]{
  /*
  def menus : List[Menu]
  がCRUDifyにより追加されます
  これをSiteMenuMapに追加しておくことでCRUD画面が作成されます。
  */

}

class AutoIncrement extends LongKeyedMapper[AutoIncrement] widh IdPK{

  def getSingleton = AutoIncrement

  /**
   IdPKにて
   object id extends MappedLongIndex(this)
   のフィールドが作成されます。
  */

}



インデックス、複合インデックスの設定のやりかた

object IndexSample extends IndexSample with LongKeyedMetaMapper[IndexSample]{

  //複合インデックス設定
  override def dbIndexes = {
    List(
      new Index(unionIndex1 , unionIndex2 , unionIndex3),
      new Index(unionIndex3 , unionIndex2)
    )
  }

}

class IndexSample extends LongKeyedMapper[IndexSample] widh IdPK{

  def getSingleton = AutoIncrement

  //フィールドのインデックス設定
  object indexForSingleField extends MappedInt(this){
    override def dbIndexed_? = true
  }
  object unionIndex1 extends MappedInt(this)
  object unionIndex2 extends MappedInt(this)
  object unionIndex3 extends MappedInt(this)

}



OneToOne , OneToMany


object MailBox ...

class MailBox extends LongKeyedMapper[MailBox] with IdPK with OneToMany[Long, MailBox]{
  
  def getSingleton = MailBox

  //one to many
  object mails extends MappedOneToMany(Mail , Mail.mailBox, OrderBy(Mail.id, Ascending))
  
}

object Mail ...

class Mail extends LongKeyedMapper[MailBox] with IdPK{
  
  def getSingleton = Mail
  //one to one(many to one)
  object mailBox extends MappedLongForeignKey(this,MailBox)

}




ManyToMany

object User ...

class User extends LongKeyedMapper[User] with IdPK with ManyToMany{

  def getSingleton = User
  
  //many to many
  object mails extends MappedManyToMany(Mail , Mail.mailBox, OrderBy(Mail.id, Ascending))
  
}
object Role...

class Role extends LongKeyedMapper[Role] with IdPK{

  def getSingleton = Role 
}

object UesrHasRole ...

class UesrHasRole extends Mapper[UserHasRole]{
  
  def getSingleton = UserHasRole
  
  object user extends LongMappedMapper(this,User)
  object role extends LongMappedMapper(this,Role)

}

2011年4月20日水曜日

Scala specsの実行順序



import org.junit.runner.RunWith
import org.specs.Specification
import org.specs.runner.{JUnit, JUnitSuiteRunner}

@RunWith(classOf[JUnitSuiteRunner])
class ExecuteOrderTest extends Specification with JUnit{

doBeforeSpec{
println("Do once before all specs")
}
doAfterSpec{
println("Do once after all specs")
}
"First" should {
doFirst{
println("Do once before all test in First")
}
doBefore{
println("Do before every test in First")
}
"hello" in {

println("Hello world")
}
"good by" in {
println("Good by world")
}
doAfter{
println("Do after every test in First")
}
doLast{
println("Do once after all test in First ")
}
}
"Second" should {
doFirst{
println("Do once before all test in Second")
}
doBefore{
println("Do before every test in Second")
}
"hello2" in {
println("Hello world2")
}
"good by2" in {
println("Good by world2")
}
doAfter{
println("Do after every test in Second")
}
doLast{
println("Do once after all test in Second ")
}
}


}


実行結果

Do once before all specs

Do once before all test in First
Do before every test in First
Hello world
Do after every test in First
Do before every test in First
Good by world
Do after every test in First
Do once after all test in First

Do once before all test in Second
Do before every test in Second
Hello world2
Do after every test in Second
Do before every test in Second
Good by world2
Do after every test in Second
Do once after all test in Second

Do once after all specs

2011年1月11日火曜日

Scalaで親クラスのオーバーロードコンストラクタを使用する

結論:Scalaで継承を行った際に、親クラスのオーバーロードされたコンストラクタを使用する方法は、ありません

どんなコードを書きたいかを、Javaで書くと


class A{
public A(){}
public A(int v){}
}
class B extends A{
public B() {super();}
public B(int v){super(v);}
}


になりますが、これをScalaで書こうとした場合、scalaではPrimaryConstructorを除くコンストラクターを呼び出せないため、単純に上記のようなコードを移植することは出来ません。

一応解決策を3つほど紹介

諦める



こんなコードは書かないようにしましょう。

デフォルト値を代入



デフォルト値がわかる場合は、デフォルト値を入れてやる

class A(){
def this( v: Int) = this()
}

class B(v : Int) extends A(v){
def this() = this(0)
}


複数のクラス作成




class A(){
def this( v: Int) = this()
}

class B1(v : Int) extends A(v)

class B2 extends A