bussorenre Laboratory

hoge piyo foo bar

Scala を書く時に他言語と混乱しないための文法備忘

Scala 初めてまだ数日勢。毎日ずっと書いていないと、元々書いていた他の言語に邪魔されて思考が途切れてしまう。 特にSwift と混合しやすい。次点で Go, javascript と混合してしまいやすい。

苦しんで自分にscala を叩き込む

宣言

val, var を使う。

val hoge = new Object()
var i = 100

特にval。よく間違えてlet とか const とか書いて怒られている。さすがにauto と書くことはない。

メソッド宣言と呼び出し

まずは宣言

def hogepiyo(arg1: type1, arg2: type2): ReturnType = {
  // write something
}

def foobar(arg1: Type1, arg2: Type2): ReturnType = foo * bar

呼び出しが少しややこしい。

qiita.com

からの抜粋になるが、

class Hoge {
  //引数リストがないメソッド
  def f1 = 1
  //引数がないメソッド
  def f2() = 1
  //引数が1つのメソッド
  def f3(x: Int) = x * 2
  //引数が複数のメソッド
  def f4(x: Int, y: Int) = x * y
}

//引数リストがないメソッド
////hoge.f1()
////hoge f1()
hoge.f1                                           //> res0: Int = 1
hoge f1                                           //> res1: Int = 1
//空行は伊達じゃないよ

//引数がないメソッド
hoge.f2()                                         //> res2: Int = 1
hoge.f2                                           //> res3: Int = 1
hoge f2()                                         //> res4: Int = 1
hoge f2                                           //> res5: Int = 1
//空行は伊達じゃないよ

//引数が1つのメソッド
hoge.f3(1)                                        //> res6: Int = 2
hoge f3(1)                                        //> res7: Int = 2
hoge f3 1                                         //> res8: Int = 2
hoge.f3 { 1 }                                     //> res9: Int = 2
hoge f3 { 1 }                                     //> res10: Int = 2
////hoge.f3 1

//引数が複数のメソッド
hoge.f4(1, 2)                                     //> res11: Int = 2
hoge f4(1, 2)                                     //> res12: Int = 2
////hoge.f4 1, 2
////hoge f4 1, 2

基本的にはjava と同じ書き方をすれば動くっちゃ動く。が、関数型っぽくないらしい。引数がない時に()を省略できるのはまぁruby とかでもやってきたから慣れれば出来る。

後置記法というらしいが、

hoge piyo

みたいな感じで、.()も省略されている場合はその次の行は空行である必要があるみたい。

hoge piyo foo

みたいな感じで、引数が一つの場合は後ろを空行にしなくてもいいらしい。この差異の意図がよくわかってない。 例文として、0 to 3 のような演算子のように使うメソッドは省略することが多い的なことが書いてあった。なんとなくわからんでもない。

あとは、副作用があるかないかでも変わる。副作用がある場合は必ずhoge.piyo(foo) みたいに書く。

コンストラクタ宣言

class Hoge(a: Type1, b:Type2) {
  require(a != b)
  // do something
  
  // auxiliary constructor
  def this(c: Type3) = this(c, c*c)
}

ruby / javascriptに近いかも。インスタンスが生成される時、上から順に実行されている。

requireでバリデーションが出来る。くっそ便利。バリデーションに失敗したら例外が帰る。

Scala ではコンストラクタはただ一つのプライマリコンストラクタを持つことが出来る。それ以外のコンストラクタは補助コンストラクタ(Auxiliary Constructor) と呼ばれ、必ずプライマリコンストラクタ(Primary Constructor)を呼ぶ必要がある。

ここはSwift で苦しんだのでわりとあっさり理解した。

制御構文

厳密にはscala には制御構文はない(本当に?) if 等は全部 if 文ではなく if 式である。 式 = statement なので、必ず結果を返す。

if式

要するに三項演算子だと思えば理解が早い。

val a = if (a or b) functionA else functionB

さて、else が必要ないときはelse を省略することが出来るが、() というUnit 型が返される(何もしないという副作用だけを返す)

if (a > 0) {
    println("hoge")
} else {
    println("piyo")
}

このようなif文のような事も普通に出来る。この時、計算結果を返さないので副作用のみを扱う関数2つを定義し、条件式でどっちを実行するか決定している。みたいなイメージになる。

if 式 というかif 関数と思えば扱いやすいのかな。3値(条件式, 関数1, 関数2)を元に演算結果を返す。みたいな。

for 式

あとで別記事で書く

まだWIP