scaladocを読むために
scaladoc読んで勉強してても記号が多いのとよく分からないキーワードが出てきて読みづらい。
気になったものを調べてまとめる。
可変長引数
以下はMap#+メソッド。*の部分。
def +(kvs: (A, B)*): Map[A, B]
implicitパラメータ
例えばList#maxByメソッド。
def maxBy[B](f: (A) ⇒ B)(implicit cmp: Ordering[B]): A
implicitが付いているメソッド引数は省略可能。省略すればデフォルトのものが適用されるが、自分で指定することも可能。
まず省略バージョン。
val list = List("one", "two", "three", "four") val result = list.maxBy(_.length) // 一番文字列長の長いthreeが返る
次に並び替えの仕組みを独自Orderingで変える。無名traitを生成して対応。
val result2 = list.maxBy(_.length){ // 一番文字列長の長いthreeが返る new Ordering[Int]{ def compare(x: Int, y: Int) = x - y } } val result3 = list.maxBy(_.length){ // 一番文字列長の短いoneが返る new Ordering[Int]{ def compare(x: Int, y: Int) = y - x } }
implicit付変数宣言をしておくと、第二引数省略してもそれが使用される。
implicit val ordering = new Ordering[Int]{ def compare(x: Int, y: Int) = y - x } val result = list.maxBy(_.length) // one
カリー化されたメソッド
以下はList#foldのscaladoc。
def fold[A1 >: A](z: A1)(op: (A1, A1) ⇒ A1): A1
このように使う。
val list = List(1,2,3,4) val result = list.fold(10)((e1,e2) => e1 + e2) // 実際の処理は10+1+2+3+4が行われる
ただ、2番目の引数は(ではなく{で記述されることが多い。
val result = list.fold(10){(e1,e2) => e1 + e2}
ジェネリクス
Ancestor > Parent > Childというようなクラス階層になっているとして。
上限境界
以下の例だと、Parent及びサブクラスChild。
class Sample[T <: Parent](x: T) {}
下限境界
以下の例だと、Parent及びスーパークラスAncestor。
class Sample[T >: Parent(x: T) {}
先のfoldメソッドのscaladocをもう一度引用すると
def fold[A1 >: A](z: A1)(op: (A1, A1) ⇒ A1): A1
となっている。このメソッドで使用するのはA1というAの下限境界型。よって、、、
class Ancestor(var x:Int) {} class Parent(var y:Int) extends Ancestor(y){} class Child(var z:Int) extends Parent(z) {} val list:List[Parent] = List(new Parent(1), new Parent(2)) val result = list.fold(new Ancestor(10)){(e1, e2) => e2.x = e1.x + e2.x; e2;}
List[Parent]に対して、変数zには親のAncestorが渡せる。この場合、A1はAncestorになるので、e1.xというアクセスになる。
一方、変数zのところを、new Parent(10)としたならば、e1.xではコンパイルエラーとなり、正しくはe1.yとなる。
共変
Mapの場合、こんなふうになっている。
trait Map[A, +B] extends Iterable[(A, B)] with GenMap[A, B] with MapLike[A, B, Map[A, B]]
このvalueの型が+となっており、共変を表す。つまり以下はOKとなる。
var map1:Map[String, Parent] = Map("k1" -> new Parent()) var map2:Map[String, Child] = Map("k2" -> new Child()) map1 = map2
ただし、keyの型は共変ではないのでこれはダメ。コンパイルエラーとなる。
var map3:Map[Parent, String] = Map(new Parent() -> "v3") var map4:Map[Child, String] = Map(new Child() -> "v4") map3 = map4
反変
もし上記Mapのvalueの型に-がついて反変だったら、Map[String, Ancestor]のインスタンスがmap1に代入できる。
Lift
Liftアプリケーション用テンプレートのDL
%git clone https://github.com/lift/lift_25_sbt.git
必要ライブラリのDL
%cd lift_25_sbt/scala_29/lift_basic
%./sbt
待つこと数分・・・
sbtプロンプトが出るので、InteliJで読み込みができるようにする。
>gen-idea
待つこと数分・・・
終了したらInteliJでOpenからlift_basicを選べば開くことが出来る。
アプリケーションを実行するには引き続きsbtプロンプト上で以下を実行。
>container:start
ブラウザで、http://localhost:8080でアクセス可能。
Intellij IDEAのsbt consoleで文字化け解消
specs2でのユニットテストの練習。
で、Intellij IDEAのsbt consoleで実行したら日本語が化ける・・・。コンソール上のsbtでも同様に日本語が化ける。。
色々調べて以下の情報に。意外と見つからなかった。
参考:http://qiita.com/items/3fd54c5b697104904176
まず文字コードのチェック。
scala> scala.io.Codec.default.charSet
res0: java.nio.charset.Charset = Shift_JIS
おぉやっぱり。俺はUTF-8で作ってるんでね。
VM引数にUTF-8であることを設定(-Dfile.encoding=UTF-8)。
再度実行。
scala> scala.io.Codec.default.charSet
res0: java.nio.charset.Charset = UTF-8
よし。テスト実行!
日本語ちゃんと表示されました。
sbt gen-idea
sbt gen-idea
を実行すると、
[error] Not a valid command: gen-idea [error] Expected '/' [error] Expected ':' [error] Not a valid key: gen-idea [error] gen-idea [error] ^
と表示された。コマンドとして認識していない模様。
標準コマンドでは無いようなのでプラグインとして追加。
plugins.sbt
addSbtPlugin("com.github.mpeltonen" % "sbt-idea" % "1.3.0")
projectフォルダに上記内容を記述したplugins.sbtを設置。
これで上記エラーはなくなりました。
あとは、Intelijでプロジェクトをオープンするだけ。
※Play frameworkだとエラーになるという情報が多くありました。