Scala Cheet Sheets (Licensed by Brendan O’Connor under a CC-BY-SA 3.0 license)の和訳。
<h4 id="variables">変数 variables</h4> | |
var x = 5 |
変数 |
Good val x = 5 Bad x=6 |
定数 |
var x: Double = 5 |
型を明示 |
<h4 id="functions">関数 functions</h4> | |
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 |
型に別名(alias)をつける |
def f(x: R) vs.def f(x: => R) |
値呼び出し(call-by-value) 名前呼び出し(call-by-name) 遅延評価されるパラメータ |
(x:R) => x*x |
無名関数(anonymous function) |
(1 to 5).map(_*2) vs.(1 to 5).reduceLeft( _+_ ) |
無名関数:_ は 関数の引数に順々にマッチする |
(1 to 5).map( x => x*x ) |
無名関数で同じ引数を二度使う場合は、名前を付けなくてはならない |
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) |
汎用(generic)型 |
5.+(3); 5 + 3 (1 to 5) map (_*2) |
中置記法の簡略 |
def sum(args: Int*) = args.reduceLeft(_+_) |
可変長引数 |
<h4 id="packages">パッケージ packages</h4> | |
import scala.collection._ |
ワイルドカード import. |
import scala.collection.Vector import scala.collection.{Vector, Sequence} |
パッケージ内でクラスを(複数)選択してimport. |
import scala.collection.{Vector => Vec28} |
クラスの名前を置き換えて import. |
import java.util.{Date => _, _} |
java.utilからすべてimportするがDateは除く. |
package pkg ファイルの先頭で package pkg { ... } |
パッケージを宣言 |
<h4 id="data_structures">データ構造 data structures</h2> | |
(1,2,3) |
タプルの表記. (Tuple3 ) |
var (x,y,z) = (1,2,3) |
構造を分解して変数に束縛: タプルはパターンマッチで分解される. |
Badvar x,y,z = (1,2,3) |
隠れた誤り:各変数にタプル全体が代入される |
var xs = List(1,2,3) |
リスト (immutable). |
xs(2) |
添字による要素へのアクセス. (slides) |
1 :: List(2,3) |
cons. |
1 to 5 以下と同じ 1 until 6 1 to 10 by 2 |
範囲指定の簡易構文 |
() (空の括弧) |
Unit型だけを受け取る関数引数の型 (C/Javaでいうvoid). |
<h4 id="control_constructs">制御構造 control constructs</h4> | |
if (check) happy else sad |
条件分岐 |
if (check) happy same as 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) |
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文による網羅: 直積 cross product を取る |
for (x <- xs; y <- ys) { ` println(“%d/%d = %.1f”.format(x,y, x*y)) <br> }` |
for文による網羅: 命令型スタイル sprintf-style |
<h4 id="pattern_matching">パターンマッチ pattern matching</h2> | |
Good (xs zip ys) map { case (x,y) => x*y } Bad (xs zip ys) map( (x,y) => x*y ) |
caseを関数定義内で使う |
Badval v42 = 42 Some(3) match { case Some(v42) => println("42") case _ => println("Not 42") } |
“v42” は任意のIntの値とマッチする変数名として解釈され、”42”が表示される. |
Goodval v42 = 42 Some(3) match { case Some(`v42`) => println("42") case _ => println("Not 42") } |
”`v42`” のように`で囲むと、既に存在するval v42 と解釈され、”Not 42”が表示される. |
Goodval UppercaseVal = 42 Some(3) match { case Some(UppercaseVal) => println("42") case _ => println("Not 42") } |
大文字からはじまるUppercaseVal は既に存在するvalとして扱われ, 新しいパターン変数とは見なされない。UppercaseVal に入っている値(42)は3 と比較されるので、”Not 42”が表示される. |
<h4 id="object_orientation">オブジェクト指向 object orientation</h4> | |
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 { ... } |
singletonを定義. (モジュールのように) |
trait T { ... } class C extends T { ... } class C extends D with T { ... } |
trait. traitをインターフェースとして使い、実装を提供. コンストラクタの引数を取らない場合. mixin-able |
trait T1; trait T2 class C extends T1 with T2 class C extends D with T1 with T2 |
複数のtraitを組み合わせる |
class C extends D { override def f = ...} |
宣言を上書きするときはoverrideを付ける |
new java.io.File("f") |
オブジェクトを生成 |
Bad new List[Int] Good List(1,2,3) |
型の誤り:抽象型は生成できない 代わりに慣習として型を隠したfactoryを使う |
classOf[String] |
classの情報を得る |
x.isInstanceOf[String] |
型があっているか検査 (実行時) |
x.asInstanceOf[String] |
型のキャスト (実行時) |
x: String |
型の記述によるチェック (コンパイル時) |