+
+ 変数 |
+ |
+
+
+ var x = 5
Good
x = 6
|
+ 変数 |
+
+
+ val x = 5
Bad
x = 6
|
+ 定数 |
+
+
+ var x: Double = 5
|
+ 明示的な型 |
+
+
+ 関数 |
+ |
+
+
+ Good def f(x: Int) = { x * x }
Bad def f(x: Int) { x * x }
|
+ 関数定義 落とし穴: = を書かないと Unit を返す手続きになり、大惨事の原因になります。 Scala 2.13 より非推奨です。 |
+
+
+ Good def f(x: Any) = println(x)
Bad def f(x) = println(x)
|
+ 関数定義 シンタックスエラー: すべての引数に型指定が必要です。 |
+
+
+ type R = Double
|
+ 型エイリアス |
+
+
+ def f(x: R) vs. def f(x: => R)
|
+ 値渡し
名前渡し(遅延評価パラメータ) |
+
+
+ (x: R) => x * x
|
+ 無名関数 |
+
+
+ (1 to 5).map(_ * 2) vs. (1 to 5).reduceLeft(_ + _)
|
+ 無名関数: アンダースコアは位置に応じて引数が代入されます。 |
+
+
+ (1 to 5).map(x => x * x)
|
+ 無名関数: 引数を2回使用する場合は名前をつけます。 |
+
+
+ (1 to 5).map { x =>
+ val y = x * 2
+ println(y)
+ y
+}
|
+ 無名関数: ブロックスタイルでは最後の式の結果が戻り値になります。 |
+
+
+ (1 to 5) filter {
+ _ % 2 == 0
+} map {
+ _ * 2
+}
|
+ 無名関数: パイプラインスタイル (括弧でも同様) 。 |
+
+
+ def compose(g: R => R, h: R => R) =
+ (x: R) => g(h(x)) val f = compose(_ * 2, _ - 1)
|
+ 無名関数: 複数のブロックを渡す場合は外側の括弧が必要です。 |
+
+
+ val zscore =
+ (mean: R, sd: R) =>
+ (x: R) =>
+ (x - mean) / sd
|
+ カリー化の明示的記法 |
+
+
+ def zscore(mean: R, sd: R) =
+ (x: R) =>
+ (x - mean) / sd
|
+ カリー化の明示的記法 |
+
+
+ def zscore(mean: R, sd: R)(x: R) =
+ (x - mean) / sd
|
+ カリー化の糖衣構文、ただしこの場合、 |
+
+
+ val normer =
+ zscore(7, 0.4) _
|
+ 部分関数を取得するには末尾にアンダースコアが必要です。 |
+
+
+ def mapmake[T](g: T => T)(seq: List[T]) =
+ seq.map(g)
|
+ ジェネリック型 |
+
+
+ 5.+(3); 5 + 3 (1 to 5) map (_ * 2)
|
+ 中間記法 |
+
+
+ def sum(args: Int*) =
+ args.reduceLeft(_+_)
|
+ 可変長引数 |
+
+
+ パッケージ |
+ |
+
+
+ import scala.collection._
|
+ ワイルドカードでインポートします。 |
+
+
+ import scala.collection.Vector import scala.collection.{Vector, Sequence}
|
+ 個別にインポートします。 |
+
+
+ import scala.collection.{Vector => Vec28}
|
+ 別名でインポートします。 |
+
+
+ import java.util.{Date => _, _}
|
+ Date を除いてjava.util のすべてをインポートします。 |
+
+
+ ファイル先頭の: package pkg
スコープによるパッケージ: package pkg {
+ ...
+}
パッケージシングルトン: package object pkg {
+ ...
+}
|
+ パッケージ宣言 |
+
+
+ data structures |
+ |
+
+
+ (1, 2, 3)
|
+ タイプリテラル (Tuple3 ) |
+
+
+ var (x, y, z) = (1, 2, 3)
|
+ 構造化代入: パターンマッチによるタプルの展開。 |
+
+
+ Bad
var x, y, z = (1, 2, 3)
|
+ 落とし穴: 各変数にタプル全体が代入されます。 |
+
+
+ var xs = List(1, 2, 3)
|
+ リスト (イミュータブル) |
+
+
+ xs(2)
|
+ 括弧を使って添字を書きます。(slides) |
+
+
+ 1 :: List(2, 3)
|
+ 先頭に要素を追加 |
+
+
+ 1 to 5 上記と同じ 1 until 6 1 to 10 by 2
|
+ Range の糖衣構文 |
+
+
+ ()
|
+ 中身のない括弧は、Unit 型 の唯一の値です。 CやJavaで言うvoid にあたります。 |
+
+
+ 制御構文 |
+ |
+
+
+ if (check) happy else sad
|
+ 条件分岐 |
+
+
+ if (check) happy
+ 上記と同様
+ if (check) happy else ()
|
+ 条件分岐の省略形 |
+
+
+ while (x < 5) {
+ println(x)
+ x += 1
+}
|
+ while ループ |
+
+
+ do {
+ println(x)
+ x += 1
+} while (x < 5)
|
+ do while ループ |
+
+
+ import scala.util.control.Breaks._
-| 変数 | |
-|----------------------------------------------------------------------------------------------------------|-----------------|
-| `var x = 5` | 変数 |
-| Good `val x = 5` Bad `x=6` | 定数 |
-| `var x: Double = 5` | 明示的な型 |
-| 関数 | |
-| Good `def f(x: Int) = { x*x }` Bad `def f(x: Int) { x*x }` | 関数定義 落とし穴: = を書かないと Unit を返す手続きになり、大惨事の原因になります。 |
-| Good `def f(x: Any) = println(x)` Bad `def f(x) = println(x)` | 関数定義 シンタックスエラー: すべての引数に型指定が必要です。 |
-| `type R = Double` | 型エイリアス |
-| `def f(x: R)` vs. `def f(x: => R)` | 値渡し 名前渡し (遅延評価パラメータ) |
-| `(x:R) => x*x` | 無名関数 |
-| `(1 to 5).map(_*2)` vs. `(1 to 5).reduceLeft( _+_ )` | 無名関数: アンダースコアは位置に応じて引数が代入されます。 |
-| `(1 to 5).map( x => x*x )` | 無名関数: 引数を2回使用する場合は名前をつけます。 |
-| Good `(1 to 5).map(2*)` Bad `(1 to 5).map(*2)` | 無名関数: 片側が束縛された中置演算。 わかりづらいので `2*_` と書くことを推奨します。 |
-| `(1 to 5).map { val x=_*2; println(x); x }` | 無名関数: ブロックスタイルでは最後の式の結果が戻り値になります。 |
-| `(1 to 5) filter {_%2 == 0} map {_*2}` | 無名関数: パイプラインスタイル (括弧でも同様) 。 |
-| `def compose(g:R=>R, h:R=>R) = (x:R) => g(h(x))` `val f = compose({_*2}, {_-1})` | 無名関数: 複数のブロックを渡す場合は外側の括弧が必要です。 |
-| `val zscore = (mean:R, sd:R) => (x:R) => (x-mean)/sd` | カリー化の明示的記法 |
-| `def zscore(mean:R, sd:R) = (x:R) => (x-mean)/sd` | カリー化の明示的記法 |
-| `def zscore(mean:R, sd:R)(x:R) = (x-mean)/sd` | カリー化の糖衣構文、ただしこの場合、 |
-| `val normer = zscore(7, 0.4)_` | 部分関数を取得するには末尾にアンダースコアが必要です。 |
-| `def mapmake[T](g:T=>T)(seq: List[T]) = seq.map(g)` | ジェネリック型 |
-| `5.+(3); 5 + 3` `(1 to 5) map (_*2)` | 中置記法 |
-| `def sum(args: Int*) = args.reduceLeft(_+_)` | 可変長引数 |
-| パッケージ | |
-| `import scala.collection._` | ワイルドカードでインポートします。 |
-| `import scala.collection.Vector` `import scala.collection.{Vector, Sequence}` | 個別にインポートします。 |
-| `import scala.collection.{Vector => Vec28}` | 別名でインポートします。 |
-| `import java.util.{Date => _, _}` | Date を除いて java.util のすべてをインポートします。 |
-| _(ファイル先頭の)_ `package pkg` `package pkg { ... }` | パッケージ宣言 |
-| データ構造 | |
-| `(1,2,3)` | タプルリテラル (`Tuple3`) |
-| `var (x,y,z) = (1,2,3)` | 構造化代入: パターンマッチによるタプルの展開。 |
-| Bad`var x,y,z = (1,2,3)` | 隠れたエラー: 各変数にタプル全体が代入されます。 |
-| `var xs = List(1,2,3)` | リスト (イミュータブル) |
-| `xs(2)` | 括弧を使って添字を書きます。 ([slides](https://www.slideshare.net/Odersky/fosdem-2009-1013261/27)) |
-| `1 :: List(2,3)` | 先頭に要素を追加 |
-| `1 to 5` _(_ `1 until 6` `1 to 10 by 2` _と同じ)_ | Range の糖衣構文 |
-| `()` _(中身のない括弧)_ | Unit 型 の唯一の値(C/Java でいう void) 。 |
-| 制御構文 | |
-| `if (check) happy else sad` | 条件分岐 |
-| `if (check) happy` _(_ `if (check) happy else ()` _と同じ)_ | 条件分岐の省略形 |
-| `while (x < 5) { println(x); x += 1}` | while ループ |
-| `do { println(x); x += 1} while (x < 5)` | do while ループ |
-| `import scala.util.control.Breaks._` `breakable {` ` for (x <- xs) {` ` if (Math.random < 0.1) break` ` }` `}`| break ([slides](https://www.slideshare.net/Odersky/fosdem-2009-1013261/21)) |
-| `for (x <- xs if x%2 == 0) yield x*10` _(_ `xs.filter(_%2 == 0).map(_*10)` _と同じ)_ | for 内包表記: filter/map |
-| `for ((x,y) <- xs zip ys) yield x*y` _(_ `(xs zip ys) map { case (x,y) => x*y }` _と同じ)_ | for 内包表記: 構造化代入 |
-| `for (x <- xs; y <- ys) yield x*y` _(_ `xs flatMap {x => ys map {y => x*y}}` _と同じ)_ | for 内包表記: 直積 |
-| `for (x <- xs; y <- ys) {` `println("%d/%d = %.1f".format(x, y, x/y.toFloat))` `}` | for 内包表記: 命令型の記述 [sprintf-style](https://java.sun.com/javase/6/docs/api/java/util/Formatter.html#syntax) |
-| `for (i <- 1 to 5) {` `println(i)` `}` | for 内包表記: 上限を含んだ走査 |
-| `for (i <- 1 until 5) {` `println(i)` `}` | for 内包表記: 上限を除いた走査 |
-| パターンマッチング | |
-| Good `(xs zip ys) map { case (x,y) => x*y }` Bad `(xs zip ys) map( (x,y) => x*y )` | case をパターンマッチのために関数の引数で使っています。 |
-| Bad `val v42 = 42` `Some(3) match {` ` case Some(v42) => println("42")` ` case _ => println("Not 42")` `}` | "v42" は任意の Int の値とマッチする変数名として解釈され、 "42" が表示されます。 |
-| Good `val v42 = 42` `Some(3) match {` `` case Some(`v42`) => println("42")`` `case _ => println("Not 42")` `}` | バッククオートで囲んだ "\`v42\`" は既に存在する `v42` として解釈され、 "Not 42" が表示されます。 |
-| Good `val UppercaseVal = 42` `Some(3) match {` ` case Some(UppercaseVal) => println("42")` ` case _ => println("Not 42")` `}` | 大文字から始まる `UppercaseVal` は既に存在する定数として解釈され、新しい変数としては扱われません。 これにより `UppercaseVal` は `3` とは異なる値と判断され、 "Not 42" が表示されます。 |
-| オブジェクト指向 | |
-| `class C(x: R)` _(_ `class C(private val x: R)` `var c = new C(4)` _と同じ)_ | コンストラクタの引数 - private |
-| `class C(val x: R)` `var c = new C(4)` `c.x` | コンストラクタの引数 - public |
-| `class C(var x: R) {` `assert(x > 0, "positive please")` `var y = x` `val readonly = 5` `private var secret = 1` `def this = this(42)` `}`| コンストラクタはクラスの body 部分 です。 public メンバ の宣言 読取可能・書込不可なメンバの宣言 private メンバ の宣言 代替コンストラクタ |
-| `new{ ... }` | 無名クラス |
-| `abstract class D { ... }` | 抽象クラスの定義 (生成不可) |
-| `class C extends D { ... }` | 継承クラスの定義 |
-| `class D(var x: R)` `class C(x: R) extends D(x)` | 継承とコンストラクタのパラメータ (要望: 自動的にパラメータを引き継げるようになってほしい)
-| `object O extends D { ... }` | シングルトンオブジェクトの定義 (モジュールに似ている) |
-| `trait T { ... }` `class C extends T { ... }` `class C extends D with T { ... }` | トレイト 実装を持ったインターフェースで、コンストラクタのパラメータを持つことができません。 [mixin-able]({{ site.baseurl }}/tutorials/tour/mixin-class-composition.html).
-| `trait T1; trait T2` `class C extends T1 with T2` `class C extends D with T1 with T2` | 複数のトレイトを組み合わせられます。 |
-| `class C extends D { override def f = ...}` | メソッドの override は明示する必要があります。 |
-| `new java.io.File("f")` | オブジェクトの生成 |
-| Bad `new List[Int]` Good `List(1,2,3)` | 型のエラー: 抽象型のオブジェクトは生成できません。 代わりに、習慣として、型を隠蔽するファクトリを使います。 |
-| `classOf[String]` | クラスの情報取得 |
-| `x.isInstanceOf[String]` | 型のチェック (実行時) |
-| `x.asInstanceOf[String]` | 型のキャスト (実行時) |
-| `x: String` | 型帰属 (コンパイル時) |
+breakable {
+ for (x <- xs) {
+ if (Math.random < 0.1)
+ break
+ }
+}
|
+ break (slides) |
+
+
+ for (x <- xs if x % 2 == 0)
+ yield x * 10
+ 上記と同様
+ xs.filter(_ % 2 == 0).map(_ * 10)
|
+ for 内包記法: filter/map |
+
+
+ for ((x, y) <- xs zip ys)
+ yield x * y
+ 上記と同様
+ (xs zip ys) map {
+ case (x, y) => x * y
+}
|
+ for 内包表記: 構造化代入 |
+
+
+ for (x <- xs; y <- ys)
+ yield x * y
+ 上記と同様
+ xs flatMap { x =>
+ ys map { y =>
+ x * y
+ }
+}
|
+ for 内包表記: 直積 |
+
+
+ for (x <- xs; y <- ys) {
+ val div = x / y.toFloat
+ println("%d/%d = %.1f".format(x, y, div))
+}
|
+ for 内包表記: 命令型の記述 sprintf-style |
+
+
+ for (i <- 1 to 5) {
+ println(i)
+}
|
+ for 内包表記: 上限を含んだ走査 |
+
+
+ for (i <- 1 until 5) {
+ println(i)
+}
|
+ for 内包表記: 上限を除いた走査 |
+
+
+ パターンマッチング |
+ |
+
+
+ Good (xs zip ys) map {
+ case (x, y) => x * y
+}
Bad (xs zip ys) map {
+ (x, y) => x * y
+}
|
+ case をパターンマッチのために関数の引数で使っています。 |
+
+
+ Bad
+ val v42 = 42
+3 match {
+ case v42 => println("42")
+ case _ => println("Not 42")
+}
|
+ v42 は任意の Int の値とマッチする変数名として解釈され、 “42” が表示されます。 |
+
+
+ Good
+ val v42 = 42
+3 match {
+ case `v42` => println("42")
+ case _ => println("Not 42")
+}
|
+ バッククオートで囲んだ `v42` は既に存在する v42 として解釈され、 “Not 42” が表示されます。 |
+
+
+ Good
+ val UppercaseVal = 42
+3 match {
+ case UppercaseVal => println("42")
+ case _ => println("Not 42")
+}
|
+ 大文字から始まる UppercaseVal は既に存在する定数として解釈され、新しい変数としては扱われません。 これにより UppercaseVal は 3 とは異なる値と判断され、 “Not 42” が表示されます。 |
+
+
+ オブジェクト指向 |
+ |
+
+
+ class C(x: R)
|
+ コンストラクタの引数。x はクラス内部からのみ利用できます。(private) |
+
+
+ class C(val x: R)
var c = new C(4)
c.x
|
+ コンストラクタの引数。自動的に公開メンバとして定義されます。(public) |
+
+
+ class C(var x: R) {
+ assert(x > 0, "positive please")
+ var y = x
+ val readonly = 5
+ private var secret = 1
+ def this = this(42)
+}
|
+ コンストラクタはクラスの body 部分 です。 public メンバ の宣言 読取可能・書込不可なメンバの宣言 private メンバ の宣言 代替コンストラクタ |
+
+
+ new {
+ ...
+}
|
+ 無名クラス |
+
+
+ abstract class D { ... }
|
+ 抽象クラスの定義 (生成不可) |
+
+
+ class C extends D { ... }
|
+ 継承クラスの定義 |
+
+
+ class D(var x: R)
class C(x: R) extends D(x)
|
+ 継承とコンストラクタのパラメータ (要望: 自動的にパラメータを引き継げるようになってほしい) |
+
+
+ object O extends D { ... }
|
+ シングルトンオブジェクトの定義 (モジュールに似ている) |
+
+
+ trait T { ... }
class C extends T { ... }
class C extends D with T { ... }
|
+ トレイト 実装を持ったインターフェースで、コンストラクタのパラメータを持つことができません。mixin-able. |
+
+
+ trait T1; trait T2
class C extends T1 with T2
class C extends D with T1 with T2
|
+ 複数のトレイトを組み合わせられます。 |
+
+
+ class C extends D { override def f = ...}
|
+ メソッドの override は明示する必要があります。 |
+
+
+ new java.io.File("f")
|
+ オブジェクトの生成 |
+
+
+ Bad new List[Int]
Good List(1, 2, 3)
|
+ 型のエラー: 抽象型のオブジェクトは生成できません。 代わりに、習慣として、型を隠蔽するファクトリを使います。 |
+
+
+ classOf[String]
|
+ クラスの情報取得 |
+
+
+ x.isInstanceOf[String]
|
+ 型のチェック (実行時) |
+
+
+ x.asInstanceOf[String]
|
+ 型のキャスト (実行時) |
+
+
+ x: String
|
+ 型帰属 (コンパイル時) |
+ |
+
+
+ Option型 |
+ |
+
+
+ Some(42)
|
+ 空ではないオプション値 |
+
+
+ None
|
+ 空のオプション値のシングルトン |
+
+
+ Option(null) == None
+Option(obj.unsafeMethod)
+ しかし以下のケースは同じではない
+ Some(null) != None
|
+ Null安全なオプション値の生成 |
+
+
+ val optStr: Option[String] = None
+ 上記と同様
+ val optStr = Option.empty[String]
|
+ 空のオプション値の明示的な型 空のオプション値の生成 |
+
+
+ val name: Option[String] =
+ request.getParameter("name")
+val upper = name.map {
+ _.trim
+} filter {
+ _.length != 0
+} map {
+ _.toUpperCase
+}
+println(upper.getOrElse(""))
|
+ パイプラインスタイル |
+
+
+ val upper = for {
+ name <- request.getParameter("name")
+ trimmed <- Some(name.trim)
+ if trimmed.length != 0
+ upper <- Some(trimmed.toUpperCase)
+} yield upper
+println(upper.getOrElse(""))
|
+ for 内包表記構文 |
+
+
+ option.map(f(_))
+ 上記と同様
+ option match {
+ case Some(x) => Some(f(x))
+ case None => None
+}
|
+ オプション値への関数の適用 |
+
+
+ option.flatMap(f(_))
+ 上記と同様
+ option match {
+ case Some(x) => f(x)
+ case None => None
+}
|
+ 上記のmap と同様だが、関数は戻り値としてオプション値を返す必要がある。 |
+
+
+ optionOfOption.flatten
+ 上記と同様
+ optionOfOption match {
+ case Some(Some(x)) => Some(x)
+ case _ => None
+}
|
+ ネストされたオプション値の展開 |
+
+
+ option.foreach(f(_))
+ 上記と同様
+ option match {
+ case Some(x) => f(x)
+ case None => ()
+}
|
+ オプション値へのプロシージャの適用 |
+
+
+ option.fold(y)(f(_))
+ 上記と同様
+ option match {
+ case Some(x) => f(x)
+ case None => y
+}
|
+ オプション値への関数の適用。空であればデフォルト値(y )を返す |
+
+
+ option.collect {
+ case x => ...
+}
+ 上記と同様
+ option match {
+ case Some(x) if f.isDefinedAt(x) => ...
+ case Some(_) => None
+ case None => None
+}
|
+ オプション値への部分的なパターンマッチの適用 |
+
+
+ option.isDefined
+ 上記と同様
+ option match {
+ case Some(_) => true
+ case None => false
+}
|
+ 空のオプション値でなければtrue を返す。 |
+
+
+ option.isEmpty
+ 上記と同様
+ option match {
+ case Some(_) => false
+ case None => true
+}
|
+ 空のオプション値であればtrue を返す。 |
+
+
+ option.nonEmpty
+ 上記と同様
+ option match {
+ case Some(_) => true
+ case None => false
+}
|
+ 空のオプション値でなければtrue を返す。 |
+
+
+ option.size
+ 上記と同様
+ option match {
+ case Some(_) => 1
+ case None => 0
+}
|
+ 空であれば0 を返し、そうでなければ1 を返す。 |
+
+
+ option.orElse(Some(y))
+ 上記と同様
+ option match {
+ case Some(x) => Some(x)
+ case None => Some(y)
+}
|
+ 値を評価し、空のオプション値であれば代替のオプション値を返す。 |
+
+
+ option.getOrElse(y)
+ 上記と同様
+ option match {
+ case Some(x) => x
+ case None => y
+}
|
+ 値を評価し、空のオプションであればデフォルトの値を返す。 |
+
+
+ option.get
+ 上記と同様
+ option match {
+ case Some(x) => x
+ case None => throw new Exception
+}
|
+ 値を返すが、空であれば例外を投げる。 |
+
+
+ option.orNull
+ 上記と同様
+ option match {
+ case Some(x) => x
+ case None => null
+}
|
+ 値を返すが、空であればnull を返す。 |
+
+
+ option.filter(f)
+ 上記と同様
+ option match {
+ case Some(x) if f(x) => Some(x)
+ case _ => None
+}
|
+ f を満たすオプション値 |
+
+
+ option.filterNot(f(_))
+ 上記と同様
+ option match {
+ case Some(x) if !f(x) => Some(x)
+ case _ => None
+}
|
+ f を満たさないオプション値 |
+
+
+ option.exists(f(_))
+ 上記と同様
+ option match {
+ case Some(x) if f(x) => true
+ case Some(_) => false
+ case None => false
+}
|
+ オプション値がf を満たす場合はtrue を返す。そうでない場合、あるいは空であればfalse を返す。 |
+
+
+ option.forall(f(_))
+ 上記と同様
+ option match {
+ case Some(x) if f(x) => true
+ case Some(_) => false
+ case None => true
+}
|
+ オプション値がf を満たす場合はtrue を返す。そうでない場合はfalse を返すが、空であればtrue を返す。 |
+
+
+ option.contains(y)
+ 上記と同様
+ option match {
+ case Some(x) => x == y
+ case None => false
+}
|
+ オプション値が値と同じか判別する。空であればfalse を返す。 |
+
+
+