Scala入門 - Scalaで書きはじめたJava使い向け


普段Javaを使っている人が、Better Java として、Scalaを触ってみようかという時に
知ってると役に立ちそうな事柄を列挙してみました。極力、javaとscalaで比較できそうな
項目を重点的に挙げています。Scala特有の機能の紹介は少なめです。


  • 開発環境
  • バージョン(2.7 と 2.8)
    • 安定版: 2.7.6 (20099月現在)
      • 2.7.6にはバグがあるので2.7.5がお勧め
      • もうすぐ、2.7.7がでる。2.7.5とほとんど同じ?
      • JDK  1.4で動く
      • 2.7.* 系列でもソースの互換性があまりない。
        • 古めのサンプルプログラムが動かない。
      • 2.7.* 系列でもバイナリ互換性がないことがあった。
        • 生成される、class ファイルの中身がかわった。
        • re-compile が必要。
    • 2.8(開発中)
      • バグfixはこちらの版に対して行われてる
      • Java5 以降で動く(Java6推奨のようです)
      • 新しい機能(named parameter等)
      • コレクションクラスを再設計
      • リリース時期はまだ未定
    • 新規に大きめのソフトを書き始めるなら 2.8 か?
  • コンパイラ(scalac)
    • オプションがいっぱい: -X , -Y
    • 途中の状態を調べる: -Xshow-phases, -Xprint:cleanup
    • 独自に拡張する: compiler plug-in
    • 相互に依存する scala と java のソースをコンパイルできる
      • 独自のjava parser をもっている
      • scalac してから javac する
    • fsc(Fast Scala Compiler)
      • daemon program
  • Javaからscalaを呼ぶ
    • scala-library.jar をクラスパスへ
    • Scalaのオブジェクトの名前に注意
      • scala の class ファイルを javap して確認する
    • @scala.reflect.BeanProperty アノテーション
      • Javaにやさしい getter , setter
      • class Foo(@reflect.BeanProperty var x) で setX, getX を生成。
      • scala からは見えない。
  • scala から Java を呼ぶ
    • Java のメソッドで、scala の予約語になってるものは、` ` で囲む
      • Thread.`yield`
  • 文法(Javaと違うところ)
    • import がすごい
      • 全ては * でなくて _
        • import java.awt._
      • 一行でimport
        • import java.awt._, javax.swing._
      • 列挙
        • import scala.collection.immutable.{Set, Map}
      • scala を省略
        • import collection.immutable.{Set, Map}
      • 一部除外
        • import collection.immutable.{Stack => _ , _}
      • 別名をつける
        • import java.lang.{List => JList}
      • 相対import
        • import Map._
        • Liftweb では頻繁に用いられている。twitter, Inc. の内部規約では使用禁止
      • "_root_" package
        • 相対importでの曖昧性を除去するために使用する。
      • final なインスタンスの field, method をインポート
        • class Foo{ def foo(){....}}; val x = (new Foo); import x._

    • コメント /* */ をネストできる
    • 一つのファイルに複数のパブリックなクラスを定義できる。
    • 一つのファイルに複数の package を定義できる。
    • なんでも変数名・メソッド名
      • UTF-8 , 記号: >> , --> , \\ 等
      • $を含んでは駄目。
    • 予約語を変数名・メソッド名に使う
      • Java を呼び出すのに必要
      • 例: Thread.`yield`
    • alias
      • 型に別名をつける: type Foo = X
      • import java.lang.{List => JList}
      • this に別名をつける:
        • inner Class から外の this を指定するのに便利
        • class Foo { self => ... }
    • Exception を catch しなくていい
    • オーバーライドするときは、override と書かないと駄目
    • 配列をつくる: Array(1,2,3)
    • 配列へのアクセスは [ ] でなくて ( )
      • Array(1,2,3)(0) ⇒ Array(1,2,3).apply(0)
      • [ ] は generics の指定のときだけに使う
    • : で終わるメソッドは、左右がひっくり返る
      • /: (foldLeft), ::
    • -> でTuple2 のインスタンスを作る
      • メソッドに渡すときに便利
        • Map.emtpy[Int, Int] + (1, 2) // エラー
        • Map.emtpy[Int, Int] + ((1, 2))
        • Map.empty[Int, Int] + (1 -> 2)
    • default parameter [2.8]
      • def sum(n:Int, total:Int=0):Int = if(n==0) total else sum(n-1, n+total)
    • named parameter [2.8]
      • def foo(widht:Int, height:Int) = { ... } ; foo(height=100, width=200)
    • primitive な型を指定できない
      • 無駄なboxed,unboxed操作が生じて効率の悪いコード生成される可能性がある
      • @specialized アノテーション [2.8]
    • メソッドをネストできる
    • メソッドの引数は常に final
    • trait で Mix-in な多重継承
    • var 変数名:型名 = 式
    • val 変数名:型名 = 式
    • def メソッド名(引数名:型名):戻りの型 = {  ..... }
    • class クラス名[型パラメータ](引数名:型名) extends ... with ... { ... }
  • 柔軟なアクセス修飾子
    • デフォルトはパブリック(public キーワードは無い)
    • private[this]
      class Foo{
      private[this] var x = 1
      def foo(f:Foo){
      f.x // compile エラー
      }
      }
    • private[クラス名], private[パッケージ名]
      package outerpkg.innerpkg
      class Outer {
      class Inner {
      private[Outer] def f()
      private[innerpkg] def g()
      private[outerpkg] def h()
      }
      }
    • protected[C] は protected または private[C] (間違ってるかも。)
    • companionの関係にある object とクラスの場合は private の制限なし
  • 記法の簡略化
    • 文区切りの ;  を改行で代用できる
    • メソッド呼び出しの .(ピリオド) を省略できる
    • Multi-Line String Literals: """ で簡単に文字列をつくる 
      """foo
      |bar""".stripMargin

    • return を省略
      • 最後の値が戻り値
      • ブロックの最後は式で無いと駄目。定義文(val,var,def等)は駄目。
    • apply を省略
    • update メソッド
    • Assignment Operators: +=, ::=, etc.
      class Foo{ def *(x:Int)=...}; var x=(new Foo) 
      x *= 1 ⇒ x = x * 1
    • match case の match を省略
      • val foo:Int => Int = {case 1 => 1; case n => n*foo(n-1) }
      • val foo:PartialFunction[Int,Int] = {case 1=>1; case n if(n>1)=>n*foo(n-1)}
    • implicit anonymous functions
      • Placeholder Systax for Anonymous Function
      • _ + _  (x, y) => x + y
    • new { .... }  ⇒ new AnyRef { ... }
    • 型推論可能であれば型指定を省略
    • クラス定義: class Foo(var name:String)
      • setter, getter を自動生成
  • 制御構文
    • if else, for, while, do while, try catch finallly, match case
    • if, try は値を返す
    • for は糖衣構文(map, filter, flatmap, foreach) (6.19 For-Comprehensions)
    • synchronized, asInstanceOf, isInstanceOf は Any クラスのメソッド
    • break, continue は無い ⇒ 必要なら自分で定義する
    • while は値を返さない
      • 常に 返り値の型は Unit
      • 末尾再帰で書き換えましょう
  • 遅延評価
    • lazy val: 変数の初期化を遅延
    • call-by-name(名前呼び出し)
      • 独自制御構文の導入
      • def If[X](b: => Boolean)(x: => X)(y: =>X) = if(b) x else y
  • 可変長引数メソッド
    • 4.6.2 Repeated Parameters
    • 可変長引数は、Seq[_] として扱う
      • def foo(x:Int*){ x.foreach(println(_))}
    • リストを可変長引数に適用
      • foo(List(1,2,3):_*)
  • Scala API
    • http://www.scala-lang.org/node/216
      • scaladoc, vscaladoc(javascriptで検索,開発停止中)
    • scala.Predef
    • scala.actors
    • scala.concurrent
      • java のThread を簡単に扱う
      • spawn, MailBox, Channel
    • scala.collection
      • mutable, immutable なコレクションクラスがある
      • Predef で、immutable なコレクションがdefault
    • scala.xml
    • scala.io
    • scala.util.parsing.combinator
      • パーサコンビネータ
    • class scala.Option
      • null って書きたくなくなる
      • if(b!=null){...} ⇒ b.foreach(...)
      • if(b!=null){...}else{...} ⇒ b.map(...).getOrElse(...)
    • class scala.Either
      • 二つの状態を保持する。例えば、エラーと正常な値
      • The Either type is often used as an alternative to scala.Option where Left represents failure (by convention) and Right is akin to Some.
    • trait scala.Iterable
      • map, flatMap, foldLeft, foldRight, filter, foreach, mkString, etc.
    • trait scala.Functionn, where n は0から22
    • trait scala.PartialFunction
    • class scala.Tuplen, where n は0から22
  • 変数定義
    • var: 再代入化
    • val: 再代入不化 java の final に相当
    • val 変数名:型名 = 式
    • 型推論可能であれば型名を省略できる
    • クラス実装時には、初期値を必ず指定
    • var foo:String = _ で null を指定
  • メソッド定義
    • def メソッド名(引数名:型名):戻りの型 = {  ..... }
    • 全てメソッド(組み込み演算子がない)
    • メソッドをネストできる
    • メソッドの引数は常に final
    • 前置単項演算子を定義できる + - ! ~ (6.12.1 Prefix Operations)
    • final な末尾再帰関数の最適化
    • 相互末尾再帰の最適化[2.8, scala.util.control.TailRec]
    • Any がルートクラス。
    • Any に AnyVal と AnyRef
    • int, byte 等の primitive 型が無い
    • Java の void に相当するのが Unit
    • Generics: covariant, contravariant
    • Structural types: ダックタイピング
      • val foo: { def length():Int } = "foo"
  • 関数オブジェクト
    • trait Function* を実装したもの
    • apply メソッドをもってる
    • 型推論で引数の型を省略可
    • (x:Int) => x+1 は new Function1[Int,Int]{def apply(x:Int) = x+1 }の省略形
    • trait Function1 は、compose andThen を持ってる
    • Function.{curried, uncurried}
    • メソッドから関数オブジェクトを生成する
      • def foo = () ; foo _
  • Trait
    • 実装をもつ interface
    • Mix-in な多重継承
    • class Foo extends Bar with T1 with T2
    • Trait の指定順に linearlize
  • case class
    • getter, stter
    • apply
    • extractor(unapply, unapplySeq)
    • 一引数の場合、 andThen, compose
    • copy [2.8]
    • Function* を自動的に実装する
  • object: Singleton の言語レベルのサポート
    • Java の static の代わりに
    • DynamicVariable: thread safe な状態を持たせる
      • 例: scala.Console
    • 5.4 Object Definitions
  • pattern match
    • case, for, 代入でパターンマッチ
      • val hd::tail = List(1,2,3)
    • 正規表現でパターンマッチ
    • extractor: unapply, unapplySeq を持つオブジェクト
    • case class
      • extractor を自動生成
    • Infix Operation Pattern
      • 2引数を持つ extractor を中間に書ける
      • case class <--->(x:Int, y:Int) ; foo match{ case x <--> y => }
    • パターンマッチに型パラメータは使えない。
    • Actor のメッセージのレシーブ
    • try catch
  • implicit conversion
  • xml が値
    • XPath ライクなアクセス: \ , \\ 
    • <foo><bar><boo>goo</boo></bar></foo> \\ "boo"

Comments