Scala日記

Scalaの備忘録。ときどき研究の話。

sbtで実行するときにstdoutにsbtのログを出さないようにする

sbt経由でプログラムを実行すると

[info] Loading project definition from...
[info] Set current project to ...
[info] Running ...

[success] Total time: 3 s, completed 2015/07/...

などが「標準出力」に出てしまって、出力をリダイレクトして処理しにくい。

そこで、

sbt --error 'set showSuccess := false'  'set outputStrategy := Some(StdoutOutput)' run

や、

sbt --error 'set showSuccess := false'  'set outputStrategy := Some(StdoutOutput)' 'runMain MainClass'

などとすると、これらを沈黙させることができる。 もちろん、これらをbuild.sbt等に直書きしておけば常に沈黙を保てる。

それでもなお

Loading ...

などが残る場合は、以下の sbt-extraをインストールして、.sbtignoreに無視したい文字列を書く。

github.com

参考文献:

  1. stackoverflow.com

Appトレイトを使って定義したmain関数を並列コレクション操作の中で呼び出すと並行に走らない。

先日のScalaハマリポイント。Appトレイトを使って定義したmain関数を並列コレクション操作の中で呼び出すと並行に走らない。問題自体の解決策は分かったが、何故そのような挙動になるのかは未解決。

あるプログラムに処理結果を吐き出させ、すぐさまその結果を読み込んで使う、という処理を並行動作させるコードを書いた。説明のために簡略化すると、このような感じ。

gist.github.com

そうすると、このような実行結果。

% sbt 'run-main ParallelWritingTest'
write 1-1.txt
write 3-1.txt
write 2-1.txt
write 4-1.txt
read 4-1.txt
read 2-1.txt
read 3-1.txt
read 1-1.txt
write 2-2.txt
write 1-2.txt
write 4-2.txt
read 4-2.txt
read 2-2.txt
read 1-2.txt
write 3-2.txt
read 3-2.txt
write 3-3.txt
write 4-3.txt
read 3-3.txt
read 4-3.txt
write 5-1.txt
write 5-2.txt
read 5-1.txt
write 5-3.txt
read 5-2.txt
read 5-3.txt
[error] (run-main-0) java.io.FileNotFoundException: 1-1.txt (No such file or directory)
java.io.FileNotFoundException: 1-1.txt (No such file or directory)
    at java.io.FileInputStream.open0(Native Method)
    at java.io.FileInputStream.open(FileInputStream.java:195)
    at java.io.FileInputStream.<init>(FileInputStream.java:138)
    at scala.io.Source$.fromFile(Source.scala:91)
        :
        :
        :
[trace] Stack trace suppressed: run last experimental/compile:runMain for the full output.
java.lang.RuntimeException: Nonzero exit code: 1
    at scala.sys.package$.error(package.scala:27)
[trace] Stack trace suppressed: run last experimental/compile:runMain for the full output.
[error] (experimental/compile:runMain) Nonzero exit code: 1
[error] Total time: 2 s, completed 2015/05/07 15:51:18

書き出されないファイルがある模様。 出来ているファイルも以下のとおり。

% ls
3-1.txt   3-2.txt   4-2.txt   4-3.txt   5-2.txt   5-3.txt   build.sbt lib       project   resources src       target

何故そうなるか分からずしばらく困っていたが、ふと第六感が働いて、Appトレイトをmix-inするのをやめてメインメソッドを直に書いたところ、想定通りの動作をした。よくわからないが、DelayedInitが何かブロッキングが起こるようなことをやっているんだろうか。

gist.github.com

% sbt 'run-main ParallelWritingTest'
[info] Running ParallelWritingTest
write 4-1.txt
write 1-1.txt
write 3-1.txt
write 2-1.txt
read 2-1.txt
read 4-1.txt
read 1-1.txt
read 3-1.txt
write 4-2.txt
read 4-2.txt
write 3-2.txt
write 2-2.txt
write 1-2.txt
write 4-3.txt
read 2-2.txt
read 1-2.txt
read 3-2.txt
read 4-3.txt
write 2-3.txt
write 3-3.txt
write 1-3.txt
read 2-3.txt
read 3-3.txt
read 1-3.txt
write 5-1.txt
read 5-1.txt
write 5-2.txt
read 5-2.txt
write 5-3.txt
read 5-3.txt
ParVector(Vector((4950,0), (4950,1), (4950,2)), Vector((9900,0), (9900,1), (9900,2)), Vector((14850,0), (14850,1), (14850,2)), Vector((19800,0), (19800,1), (19800,2)), Vector((24750,0), (24750,1), (24750,2)))
[success] Total time: 1 s, completed May 7, 2015 1:28:39 PM

型消去の結果同じ引数型になってしまうメソッドをオーバーロードする その2

以前の話の続き。

ym.hatenadiary.jp

DummyImplicitという型を使って下のような書き方をする作法もあるらしい。

gist.github.com

使わない暗黙のパラメータを取ることで引数リストの数を区別しようというもの。 ちなみに、DummyImplicitscala.Predefの中で

class DummyImplicit

object DummyImplicit {
  implicit def dummyImplicit: DummyImplicit = new DummyImplicit
}

とされているので、何もしなくてもこの暗黙のパラメータは解消される。 ダミーの暗黙のパラメータを使って区別する場合はこれを使うのがよい作法に思える。

implicit i1: DummyImplicitとかいちいち書くのが面倒くさければ、 ClassTagを使って少し短く書ける。

gist.github.com

どちらにしても相当気持ち悪い見た目をしていることには変わりない。 前回の方法とどちらを好むかは趣味がわかれるところ。

参考文献: 1. stackoverflow.com

  1. stackoverflow.com

Arrayをprintしたい時は deep

ScalaのArrayは前回の問題のせいで、toStringで要素の値を文字列に出来ないが、WrappedArrayというラップ型に変換すれば中身も文字列化される。このため、適当にtoSeqなどして表示するわけだが、WrappedArrayという文字列が長くてイライラするし、多次元配列等の場合はめんどくさい。そこで、.deepとすれば、多次元配列を再帰的にWrappedArrayに変換してくれる上に、"WrappedArray"という型を表す長々としたプレフィックス文字列を"Array"で上書きしてくれる。 こういうの欲しかったんです。ありがたい。

でもSeq[Seq[Array[Int]]]みたいなときには結局困るので、もうつまりArrayは使うなということかもしれない…。