diff --git a/_ja/cheatsheets/index.md b/_ja/cheatsheets/index.md index 7304890aff..f34596a8cf 100644 --- a/_ja/cheatsheets/index.md +++ b/_ja/cheatsheets/index.md @@ -13,78 +13,610 @@ language: ja ###### Contributed by {{ page.by }} {{ page.about }} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
変数
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 は既に存在する定数として解釈され、新しい変数としては扱われません。 これにより UppercaseVal3 とは異なる値と判断され、 “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を返す。