Showing all posts tagged scala:

Someにタプルを渡したら「Adapting argument list by creating a 4-tuple: this may not be what you want」という警告を受けた

Optionにタプルを包もうと考え、以下の例のように書きました。


Some(userId, None, Some(itemId), item)

すると -Xlint オプションのお陰で、以下のように警告されました。


Adapting argument list by creating a 4-tuple: this may not be what you want.

[warn]         signature: Some.apply[A](x: A): Some[A]

[warn]   given arguments: userId, None, Some(itemId), item

[warn]  after adaptation: Some((userId, None, Some(itemId), item))

[warn]           Some(userId, None, Some(itemId), item)

「はて、うまく渡っているようだが、どういうことだろう」と考え、その前で @unchecked アノテーションを付けるなどしてみたがうまくいかず。

この警告の意味は要するに、

「Someの引数はひとつなのに、与えられた引数は4つもある。仕方がないからタプルに変換して渡してやったが、これはアンタの考えている挙動と異なるかもしれないから、よく確認しろ!」

ということです。

以下のように、タプルを明示的に渡してあげると、警告はなくなりました。ちゃんとタプルとして渡せているのかどうか、注意しなければなりませんね。


Some((orderDetail.sellerId, None, Some(orderDetailComment.orderDetailId), orderDetail))

安易に警告を抑制(@suppressWarnings)できなくてよかったです。

参考

引数の数間違えたと思ったらタプルになってた

CreationException: Unable to create injector

原因:jdbcとplay-slickが依存性に含まれていると、それぞれがplay.api.db.DBApiを使用するので、競合してエラーとなる。

対策:jdbcの除去

参考:play-framework > [play 2.4.0-RC5 Scala] evolutions and injector error with play-slick

! @6mk485065 - Internal server error, for (GET) [/] ->

play.api.UnexpectedException: Unexpected exception[CreationException: Unable to create injector, see the following errors:

1) A binding to play.api.db.DBApi was already configured at play.api.db.slick.evolutions.EvolutionsModule.bindings(EvolutionsModule.scala:14):
Binding(interface play.api.db.DBApi to ConstructionTarget(class play.api.db.slick.evolutions.internal.DBApiAdapter) in interface javax.inject.Singleton) (via modules: com.google.inject.util.Modules$OverrideModule -> play.api.inject.guice.GuiceableModuleConversions$$anon$1).
  at play.api.db.DBModule.bindings(DBModule.scala:25):
Binding(interface play.api.db.DBApi to ProviderConstructionTarget(class play.api.db.DBApiProvider)) (via modules: com.google.inject.util.Modules$OverrideModule -> play.api.inject.guice.GuiceableModuleConversions$$anon$1)

1 error]
    at play.core.server.DevServerStart$$anonfun$mainDev$1$$anon$1$$anonfun$get$1$$anonfun$apply$1$$anonfun$1.apply(DevServerStart.scala:165) ~[play-server_2.11-2.4.1.jar:2.4.1]
    at play.core.server.DevServerStart$$anonfun$mainDev$1$$anon$1$$anonfun$get$1$$anonfun$apply$1$$anonfun$1.apply(DevServerStart.scala:121) ~[play-server_2.11-2.4.1.jar:2.4.1]
    at scala.Option.map(Option.scala:146) ~[scala-library-2.11.6.jar:na]
    at play.core.server.DevServerStart$$anonfun$mainDev$1$$anon$1$$anonfun$get$1$$anonfun$apply$1.apply(DevServerStart.scala:121) ~[play-server_2.11-2.4.1.jar:2.4.1]
    at play.core.server.DevServerStart$$anonfun$mainDev$1$$anon$1$$anonfun$get$1$$anonfun$apply$1.apply(DevServerStart.scala:119) ~[play-server_2.11-2.4.1.jar:2.4.1]
    at scala.util.Success.flatMap(Try.scala:230) ~[scala-library-2.11.6.jar:na]
    at play.core.server.DevServerStart$$anonfun$mainDev$1$$anon$1$$anonfun$get$1.apply(DevServerStart.scala:119) ~[play-server_2.11-2.4.1.jar:2.4.1]
    at play.core.server.DevServerStart$$anonfun$mainDev$1$$anon$1$$anonfun$get$1.apply(DevServerStart.scala:111) ~[play-server_2.11-2.4.1.jar:2.4.1]
    at scala.concurrent.impl.Future$PromiseCompletingRunnable.liftedTree1$1(Future.scala:24) ~[scala-library-2.11.6.jar:na]
    at scala.concurrent.impl.Future$PromiseCompletingRunnable.run(Future.scala:24) ~[scala-library-2.11.6.jar:na]
    at java.util.concurrent.ForkJoinTask$RunnableExecuteAction.exec(ForkJoinTask.java:1423) ~[na:1.8.0_05]
    at java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:289) ~[na:1.8.0_05]
    at java.util.concurrent.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:902) ~[na:1.8.0_05]
    at java.util.concurrent.ForkJoinPool.scan(ForkJoinPool.java:1689) ~[na:1.8.0_05]
    at java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1644) ~[na:1.8.0_05]
    at java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:157) ~[na:1.8.0_05]
Caused by: com.google.inject.CreationException: Unable to create injector, see the following errors:

1) A binding to play.api.db.DBApi was already configured at play.api.db.slick.evolutions.EvolutionsModule.bindings(EvolutionsModule.scala:14):
Binding(interface play.api.db.DBApi to ConstructionTarget(class play.api.db.slick.evolutions.internal.DBApiAdapter) in interface javax.inject.Singleton) (via modules: com.google.inject.util.Modules$OverrideModule -> play.api.inject.guice.GuiceableModuleConversions$$anon$1).
  at play.api.db.DBModule.bindings(DBModule.scala:25):
Binding(interface play.api.db.DBApi to ProviderConstructionTarget(class play.api.db.DBApiProvider)) (via modules: com.google.inject.util.Modules$OverrideModule -> play.api.inject.guice.GuiceableModuleConversions$$anon$1)

1 error
    at com.google.inject.internal.Errors.throwCreationExceptionIfErrorsExist(Errors.java:466) ~[guice-4.0.jar:na]
    at com.google.inject.internal.InternalInjectorCreator.initializeStatically(InternalInjectorCreator.java:155) ~[guice-4.0.jar:na]
    at com.google.inject.internal.InternalInjectorCreator.build(InternalInjectorCreator.java:107) ~[guice-4.0.jar:na]
    at com.google.inject.Guice.createInjector(Guice.java:96) ~[guice-4.0.jar:na]
    at com.google.inject.Guice.createInjector(Guice.java:73) ~[guice-4.0.jar:na]
    at com.google.inject.Guice.createInjector(Guice.java:62) ~[guice-4.0.jar:na]
    at play.api.inject.guice.GuiceBuilder.injector(GuiceInjectorBuilder.scala:126) ~[play_2.11-2.4.1.jar:2.4.1]
    at play.api.inject.guice.GuiceApplicationBuilder.build(GuiceApplicationBuilder.scala:93) ~[play_2.11-2.4.1.jar:2.4.1]
    at play.api.inject.guice.GuiceApplicationLoader.load(GuiceApplicationLoader.scala:21) ~[play_2.11-2.4.1.jar:2.4.1]
    at play.core.server.DevServerStart$$anonfun$mainDev$1$$anon$1$$anonfun$get$1$$anonfun$apply$1$$anonfun$1$$anonfun$2.apply(DevServerStart.scala:153) ~[play-server_2.11-2.4.1.jar:2.4.1]
    at play.core.server.DevServerStart$$anonfun$mainDev$1$$anon$1$$anonfun$get$1$$anonfun$apply$1$$anonfun$1$$anonfun$2.apply(DevServerStart.scala:150) ~[play-server_2.11-2.4.1.jar:2.4.1]
    at play.utils.Threads$.withContextClassLoader(Threads.scala:21) ~[play_2.11-2.4.1.jar:2.4.1]
    at play.core.server.DevServerStart$$anonfun$mainDev$1$$anon$1$$anonfun$get$1$$anonfun$apply$1$$anonfun$1.apply(DevServerStart.scala:150) ~[play-server_2.11-2.4.1.jar:2.4.1]
    ... 15 common frames omitted

Scala: ファイルの内容を一行ずつ処理したい

java.nio.file.Filesで一行ごとに処理(ただしScala)

Java SE 7のjava.nio.file.Filesがとても便利な件

ファイルの内容を一行ずつ読み込んで処理したい場合に、今まではこちらのページ:(Fileの読み込み - Scala覚書)を参考に実装していましたが、nioを使えば簡単だったので、メモしておきます。

val file = Paths.get(path)
Files.readAllLines(file, Charset.defaultCharset())
     .foreach(println)

Charset.defaultCharset()が鬱陶しいですがそれに目を瞑ればシンプルです。 scala.io.Sourcejava.io.BufferedReadercommons.io.FileUtils だといずれもバッファをクローズする必要があるので、それに比べればだいぶ良いのではないでしょうか。

巨大なファイルのとき

これは、scala.io.Sourceを利用するのがよさそう。構造的部分型を利用したローンパターンを使わなければならないので、そのぶんコードが膨らみますが、そのぶん使用箇所はシンプルにまとまります。

using(Source.fromFile("file.txt")) {
     _.getLines().foreach(println)
}

def using[A <% { def close():Unit }](s: A)(f: A=>Any) {
     try f(s) finally s.close()
}

また、using内でSourceのもつメソッドを十分に活用したい場合は、構造的部分型での一般化を諦める必要があります。
参考:Scala using(ローンパターン)-Hishidama's Scala Memo-

変数に対してString Interpolationを適用する

皆さんお馴染みのString Interpolationですが、すでにある変数に対してString Interpolationを適用したいと思ったのでメモします。

String Interpolation自体は、以下のように、文字列にあとから変数を挿入する機能です。

scala> val x = "interpolation"
scala> println(s"string #{x}")
string interpolation

詳しくはこちら。 http://docs.scala-lang.org/ja/overviews/core/string-interpolation.html## 何がしたいの?

すでにあるstring interpolationを含んだ文字列に、あとからString Interpolationを適用したいということです。何を言っているかわからないと思いますが、概念的にはこういうことです。
```scala> val a = "string ${x}"
scala> val x = "interpolation"
scala> println(s(a))
string interpolation


試しに入れ子にしてみます。

scala> println(s"${a}")
string ${x}
```

ダメですよね。すみません。

無理みたいです

http://stackoverflow.com/questions/13260864/string-interpolation-in-scala-2-10-how-to-interpolate-a-string-variable

「コンパイル時に情報が不足してしまうから」とのことで、納得。

http://kmizu.hatenablog.com/entry/20120505/1336216839

Scala雑なまとめ(随時更新)ver. 0.0.2

便利なライブラリ

Finagle

Scala School

Pants Build System

Gatling

Colossus

Scala便利なサイト

Scala Best Practices

https://github.com/alexandru/scala-best-practices

Typesafe Activator使い方

プロジェクトを開く

当該ディレクトリにて ./activator

新規プロジェクト

$ ./activator new

または

new newproject

Eclipse設定ファイル生成

eclipse

ソース付き

eclipse with-source=true

参考リンク

http://www.mwsoft.jp/programming/scala/typesafe_activator_eclipse.html