Skip to content

Instantly share code, notes, and snippets.

@hayasshi
Last active August 29, 2015 14:23
Show Gist options
  • Save hayasshi/ba1ed88880ff4eb01d32 to your computer and use it in GitHub Desktop.
Save hayasshi/ba1ed88880ff4eb01d32 to your computer and use it in GitHub Desktop.
Programing in Scala

Chapter 2

Scalaプログラミングの第一歩

  • Scalaインタープリタ(REPL)
  • 変数、定数
  • 関数(メソッド)
  • whileループ
  • ifループ
  • インクリメンタル演算子、デクリメント演算子はない
  • foreachとforによる反復実行
  • Scalaスクリプト

Chapter 3

Scalaプログラミングの次の一歩

  • 配列と型パラメータ
val greetString = new Array[String](3)
greetString(0) = "Hello"
greetString(1) = ", "
greetString(2) = "world!"
for (i <- 0 to 2) {
  println(greetString(i))
}

greetString(2) = "hayasshi!"
for (i <- 0 to 2) {
  println(greetString(i))
}
  • Scalaのメソッドについて
greetString(0) == greetString.apply(0)
(greetString(0) = "foobar") == greetString.update(0, "foobar")
  • リスト
val list1 = List(1, 2, 3) // List.apply[Int](1, 2, 3)
val list2 = 1 :: 2 :: 3 :: Nil
println(list1 == list2)
println(list1 ::: list2) // list1 ++ list2
val t1 = (1, "two") // Tuple2.apply[Int, String](1, "two")
println(t1._1)
println(t1._2)
val (a, b) = t1 // t1.unapply
val t23 = (1, "two", '3', ..., 23)
  • 集合とマップ

    • scala.collection.Set
      • scala.collection.immutable.Set
      • scala.collection.mutable.Set
      val mSet = scala.collection.mutable.Set(1, 2, 3)
      val imSet = scala.collection.immutable.Set(1, 2, 3)
      println(mSet += 4)  // Set(1, 2, 3, 4)
      println(imSet += 4) // Set(1, 2, 3, 4)
      println(mSet)  // Set(1, 2, 3, 4)
      println(imSet) // Set(1, 2, 3)
    • scala.collection.Map
      • scala.collection.immutable.Map
      • scala.collection.mutable.Map
      val mMap = scala.collection.mutable.Map(1 -> "one", 2 -> "two")
      val imSet = scala.collection.immutable.Map(1 -> "one", 2 -> "two")
      println(mMap += (3 -> "three"))  // Map(1 -> "one", 2 -> "two", 3 -> "three")
      println(imMap += (3 -> "three")) // Map(1 -> "one", 2 -> "two", 3 -> "three")
      println(mMap)  // Map(1 -> "one", 2 -> "two", 3 -> "three")
      println(imMap) // Map(1 -> "one", 2 -> "two")
  • List, Set, Mapについては少々情報が古くなっているので下記資料を参考

  • 関数型のスタイルを見つける

    • varとval
    • 副作用のない関数、メソッド
      • 副作用を局所化しテストしやすい設計を
    • まずはval、イミュータブルオブジェクト、副作用のないメソッドを使うことを心がける
      • どう書いてよいかわからない時は相談しよう
      • 明確な理由がある場合のみ、var、ミュータブルオブジェクト、副作用のあるメソッドをつかう
  • ファイルから行を読み出す

Chapter 4 クラスとオブジェクト

クラス、フィールド、メソッド

  • 基本的にJavaと同じ
class ScalaClass {
  val myField = "hoge"
  private var myStatus = "01"

  def run(): String = {
    setStatus("02")
    myStatus
  }

  def end(): String = {
    setStatus("03")
    myStatus
  }

  private def setStatus(status: String) {
    myStatus = status
  }
}
  • メソッド引数は"val"

  • returnは省略できる

    • 早期returnは使わない
    • メソッドは1つの値を生成する式→設計レベルで意識する必要あり
  • メソッドのシグネチャと実装の間の"="に注意

    • "="が無いと(手続き型記述)返り値がすべてUnitになる
def a() {
  "hoge"
}
def b(): Unit = "hoge"

セミコロンの扱い

  • セミコロンは基本的に不要
    • 1行に複数文記載する場合に使用する
    • 復数文またがる場合もScalaが分割
// OK
if (flag)
  println("true")
else
  println("false")

// NG
val sum = x
+ y
  • セミコロン推論の規則 次の条件に当てはまる場合は、行末セミコロンとして扱われない
    1. 該当行の末尾が、ピリオドや中置演算子などの文の末尾として文法的に認められていない単語になっている
    2. 次の行の先頭が、文の先頭として認められない単語になっている
    3. 括弧()や角括弧[]の中にいる状態で文末になっている

シングルトンオブジェクト

  • Scalaはstaticメンバを持てない

    • 代わりにシングルトンオブジェクト(Singleton Object)を利用できる
  • obectキーワードで指定する

object ScalaStatic {
  val value = "hoge"
}
println(ScalaStatic.value)
  • staticと同じようなものだが、フィールドやメソッドは同名のクラスに属していない

    • Javaはクラスの共通領域で管理される
    • シングルトンオブジェクトはそれが唯一のインスタンスとして扱われる
  • シングルトンオブジェクトと同じ名前のクラスがある場合、下記のような呼び方をされる

    • シングルトンオブジェクト→コンパニオンオブジェクト
    • 同名のクラス→コンパニオンクラス
    • 同一のソースファイルに記載される必要がある
    • コンパニオン同士はお互いの非公開メンバにアクセスできる
    • 逆にコンパニオンクラスのないシングルトンオブジェクトは「スタンドアロンオブジェクト」と呼ばれる
class Sample {
  private val value = "foo"
}
object Sample {
  private val value = "bar"
}
// それぞれのvalueは別物
  • コンパニオンオブジェクトはクラスとは別のクラスやトレイトを継承・ミックスインできる

  • Javaのバイトコード的にはstatic領域に無名内部クラスのインスタンスがセットされる

    • 初期化セマンティクスがJavaのstaticメンバと同じ
    • 最初にアクセスされた時に初期化される

Scalaアプリケーションのエントリーポイント

  • Scalaのエントリーポイント(プログラム実行開始)は、スタンドアロンオブジェクトのmainメソッド
object HogeFuga {
  def main(args: String): Unit = {
    // run program
  }
}
  • Scalaはソースファイルに好きな名前をつけることができるが慣習的にJavaと同じ命名規則が用いられる

  • Scalaのソースは暗黙的に下記のパッケージやオブジェクトがインポートされる

    • java.lang._
    • scala._
    • scala.Predef._

Chapter 5 基本型と演算子

基本型

値型 範囲
Byte 2の補数表現の8ビット符号付き整数
Short 2の補数表現の16ビット符号付き整数
Int 2の補数表現の32ビット符号付き整数
Long 2の補数表現の64ビット符号付き整数
Char 16ビット符号なしUnicode文字
String Charのシーケンス
Float 32ビットのIEEE754単精度浮動小数点
Double 64ビットのIEEE754倍精度浮動小数点
Boolean true または false
  • int, doubleなども使えるが、いつ削除されるかわからない

リテラル

  • 整数リテラル、浮動小数点リテラル、文字リテラル、BooleanリテラルはJavaと同じ
  • 文字列リテラルも基本は同じだがヒアドキュメントがある
    • """〜〜〜""" のようにダブルクォート3つで開始終了
    val s1 = """foo
                bar"""
    val s2 = """|foo
                |bar""".stripMargin
    println(s1)
    println(s2)

シンボル(Symbol)

  • 文字列みたいなもの
  • そのJVMプロセスで同じシンボルは同じインスタンスを表す
  • 'foobar == Symbol("foobar")

演算子

  • Scalaの演算子はすべてメソッド
  • 1 + 2 == 1.+(2) の糖衣構文
  • 自分で作るメソッドにも記号が使えるので演算子を作れる
  • 中置(infix)演算子
  • 前置(prefix)演算子
  • 後置(postfix)演算子
    • 前置、後置演算子は単項(unary)演算子
    • 単行演算子で使用でき記号は「+,-,!,~」
    • 例えば-2.0は「(2.0).unary_-」
    • 例えば!trueは「(true).unary_!」
  • メソッドで引数を取らないメソッドは()を省略できる
    • 10.toString
    • 慣習的に副作用のないものは省略する
    • 慣習的に副作用のあるものは省略しない
  • 算術演算(+,-,*,/,%)、関係演算(<,>,<=,>=,!)、論理演算(&&,||)
  • ビット演算(&,|,^,~)
  • 等価演算(==,!=)
    • Javaとはことなりオブジェクト参照の等価ではない
    • null安全
    • 内部的には左辺がnullでなければequalsメソッドをつかう
      • case classは自動でequalsメソッドをオーバーライド
    • 参照の等価をチェックするには「eq,ne」メソッドを利用する

演算子の優先順位

  • 演算子(メソッド)の評価順序は、メソッドの先頭文字によって優先順位が決められている

    優先順位 記号
    (他のすべての特殊文字)
    * / %
    + -
    :
    = !
    < >
    &
    ^
    |
    (すべての英字)
    (すべての代入演算子)
  • Javaと同じくわからなくなりそうであれば()でくくったり別式(別行)で記述する

リッチラッパー

  • [1 max 2]や["32".toInt]のような基本型には含まれないメソッドが使える
  • Scalaではコンパイル時にscala.runtimeパッケージにあるリッチラッパーに暗黙の型変換が行われる
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment