Version 64 (modified by keisuken, 5 years ago)

--

Scala Sandbox TOP

Scala-sandbox-docs

Scala-sandboxの文書ページです.

技術情報やライブラリの使い方,FAQ(Q&A)などがここに書かれます.

なお,このページとは別にScala-sandboxのトップページがあります.

技術情報

文法

  • val
    • valで定義した変数は、一度値を設定した後は更新することができません (Javaのfinalのようなものです)。あくまで、更新できないのは変数の値で であって、変数が指している先のオブジェクトを変更することは可能であることに 注意してください(この点もJavaのfinalと同じです)。
      val a :Int = 10
      a = 20 // エラー。valで定義した変数の値を更新することはできない
      
      val a = 10 // 変数の型は省略可能
      
      val b:Array[Int] = Array(1, 2, 3)
      b(0) = 2 // OK。変数が指しているオブジェクト(配列)の内容は更新できる
      
  • var
    • varで定義した変数は、値を更新することができる変数になります (Javaの通常の変数と同じ)。
      var a :Int = 10
      a = 20 // OK。
      
      var a = 10 // 変数の型は省略可能
      
  • for
    • for文は、Javaの拡張for文と同じように使えます
      // 1から10まで1つずつ加算しながらループ
      for (i <- 1 to 10) {
        printf("{0} ", i)
      }
      
      > 1 2 3 4 5 6 7 8 9 10 
      
      // 0から9まで1つずつ加算しながらループ
      for (i <- 0 until 10) {
        printf("{0} ", i)
      }
      
      > 0 1 2 3 4 5 6 7 8 9 
      
      // Int型の配列でループ
      for (value <- Array(1, 2, 3, 4)) {
        printf("{0} ", value)
      }
      
      > 1 2 3 4 
      
    • 関数型言語でよく使われるmapやfilterにも対応しています
      // map
      val values = for (value <- Array(1, 2, 3, 4)) yield {
        value.toString
      }
      
      > Array[java.lang.String] = Array(1, 2, 3, 4)
      
      // filter
      val values = for {value <- Array(1, 2, 3, 4); if (value % 2) == 0} yield {
        value.toString
      }
      
      > Array[java.lang.String] = Array(2, 4)
      
  • ブロック/クロージャ
  • class
    • Javaのclassとほぼ同じ意味として使えます
      class Hello {
        def greeting(msg: String): String = {
          msg + ", world!"
        }
      }
      
      class Person {
        var _name = ""
        def name: String = _name
      }
      
    • クラス定義とコンストラクタを同時に書けます
      class Person(_name: String) {
        def name: String = _name
      }
      
    • コンストラクタの派生を書くことができます
      class Person(_name: String) {
        def this() = {
          this("")
        }
      }
      
    • クラスなどを継承できます
      class Foo(foo: String) {
      }
      
      class Boo(foo: String, boo: Integer) extends Foo(foo) {
      }
      
  • trait
  • object
  • case class
  • パターンマッチ
  • apply
  • unapply
  • implicit
  • 演算子を定義したい
  • 単項演算子を定義したい
    • 単項の前置演算子としてユーザが定義できるのは、+,-,!,~の4種類です。
      class P {
        def unary_+ :Int = 1 // unary_`operator_name`の形で定義
      }
      println(+new P) // 1
      
      のような形でメソッドを定義および使用することができます。
    • 単項の後置演算子はScalaでは通常のメソッドと同じように定義します。
      class P {
        def + :Int = 1
      }
      println(new P+) // 1
      

def

  • setterを定義したい
  • getterを定義したい
  • 可変長引数を定義したい
    • 可変長引数を取るメソッドは以下のようにして定義することができます。最後の引数 の型名の後に*を付けることで、その引数が可変長引数になります。メソッド内部 での可変長引数の扱いは配列と似ていますが微妙に違うので、配列を受け取るメソッド などに可変長引数を渡したい場合、toArrayメソッドを使用しましょう。
      def printAll(xs :Int*) {
        for(x <- xs) print(x)
        println()
      }
      ...
      printAll(1, 2, 3) // => 123
      
  • 可変長引数を取るメソッドに配列などのオブジェクトを展開した要素を渡したい
    • 可変長引数を取るメソッドの実引数の後ろに:_*を付けることで可能です。
      def printAll(xs :Int*) {
        for(x <- xs) print(x)
        println()
      }
      ...
      printAll(Array(1, 2, 3):_*) // => 123
      
  • 「可変長引数を引数に取る関数」の型を記述したい
    • val f :Int* => Unit = ...だと構文エラーになります。 val f :(Int*) => Unit = ...のように、可変長引数の型を丸括弧でくくってください。
  • 注意:可変長引数を持つ関数のオーバロードには注意が必要
    • 可変長引数は、内部的にscala.Seqに変換される。よって、例えば以下のように引数の型が違う様に見えても、内部的には同じtest(scala.Seq)になってしまうため、コンパイル出来ない。
      def test(i:Int*   ) = "hoge"
      def test(s:String*) = "piyo"
      

FAQ(Q&A)

Javaからの移行

  • Scalaのfor文はJavaのfor文と違うようですが
    • 確かに意味はかなり違いますが,ほぼ同じ事ができます
      Java:  for(int i = 0; i < 10; i++) { ... }
      Scala: for(i <- 0 until 10) { ... }
      
      Java:  for(int i = 0; i <= 10; i++) { ... }
      Scala: for(i <- 0 to 10) { ... }
      
      Java:  for(String str : new String[] {"aaa", "bbb", "ccc"}) { ... }
      Scala: for(str <- Array("aaa", "bbb", "ccc")) { ... }
      
  • Scalaのwhile文の中にロジックを書きたい
    • Scalaのwhile文はループの評価式しか書けませんのでブロックを使って書きます
      Java:
        int len;
        while((len = in.read(b)) > 0} { ... }
      Scala:
        val len: Int = 0
        while({len = in.read(b); len > 0}) { ... }
      
  • Javaのコレクションを使いたい
    • scala.collection.jcl._を使いましょう.Scalaによって機能が拡張されますしGenericsも扱う事ができます
  • メソッドをsynchronizedしたい
    Java:  synchronized void foo() { ... }
    Scala: def foo() = synchronized { ... }
    
  • オブジェクトをsynchornizedしたい
    Java:  synchornized(foo) { ... }
    Scala: foo.synchronized { ... }
    
  • Javaのequals相当のことをするには?
    • Anyクラスのequalsまたは==メソッドを使いましょう。逆にJavaの==相当のことをしたいときは、 AnyRefクラスのeqメソッドを使います。

困った

  • パッケージ名に「scala」という名前があると,importできません
    • Scalaでは相対的にimportする事ができますが,パッケージ名に「scala」という名前があるとScala本来のパッケージをimportできなくなります.importするときに_root_.を先頭に 付加することで回避できますが、パッケージ名に「scala」という名前を含めない方が無難 でしょう。
      import _root_.scala.collection.mutable._
      
  • 予約語と同じ名前のメソッド(ex. Thread.yieldなど)を呼び出しできない
    • Thread.yieldの場合は,yieldが予約語で登録されているため,そのままでは呼び出しできません.この場合は,`名前`と書きます
      Thread.`yield`()
      
  • i1 & i2 != 0がコンパイルエラーになる
    • Javaと演算子の優先順位が違っているためです。括弧を使って(i1 & i2) != 0 とすることでコンパイルが通るようになります。

ソース(src)の説明

リンク

  1. 公式
  2. ドキュメント
  3. ライブラリ
    • Scala Actors:Actor関連
    • ScalaTest: Scalaテストフレームワーク
    • Specs: BDDなテストフレームワーク
    • Lift: Webアプリケーションフレームワーク
  4. 情報源
  5. 紹介記事
  6. ブログ
  7. その他、サンプルコードなど