変数・基本構文

1. 変数

値を保持する箱のようなものです。アセンブリ言語ではレジスタ、メモリーとかと具体的な場所が対象だったのですが、抽象化されて自由な名前で宣言加能です。
変数の宣言方法は2種類あります。

val ・・・ 一度宣言すると値の変更不可。
var ・・・ 何度でも値を変更可能。

私は、『定数宣言』がある言語(Java, VB)しか馴染みがなかったので、val にすごく違和感がありました。
しかも書籍やサイトを見る限りは、var では無く、 valを基本的に使うように推奨されています。
但し、var が完全に否定されているわけではありません。
val で表現できない場合のみ、varを利用すべきだと言う事のようです。
変更可能なvar を使う事により、予期せず値が変わってしまうことを避け、
val を利用する事により、何をパラメータとして処理に与えないといけないかを考えさせてくれると思います。
最終的には、変数をなるべく減らし、短い関数で表現する事が目的のようです。

// Int(整数型) の 変数 x を宣言
val x : Int = 1
// NG!! 『val』の場合は再設定できない。
x = 2
// 型の宣言が無くても定義が可能
var y = 3   
// var の場合は後から変更可能
y = 4

上記の様に『:Int』と型宣言を記述しなくても、変数は宣言できます。
これは『型推論』と呼ばれるScalaの特徴です。このように自明な場合には、コードを省略できる構文がScalaには数多く存在します。

なお、Scala のデータ型としては下記のデータ型が存在します。
Byte、Short、Int、Long、Char、String、Float、Double、Boolean

2. lazy val (遅延評価 val)

変数を呼び出す際に、実際の処理を呼ぶように定義する事ができます。

以下は、遅延評価していない通常の変数宣言です。 val 宣言ブロックの printlnが先に呼ばれてしまっています。

val twit = {
  println("2. すごく重い初期化処理")
  List("aaa", "bbb", "ccc")
}

println("1. ここから処理が始まる")
println(twit)

// 2. すごく重い初期化処理
// 1. ここから処理が始まる
// List(aaa, bbb, ccc)

ここにlazyを付与する事で、変数を実際に利用する際に、その定義が呼ばれます。

lazy val twit = {
  println("2. すごく重い初期化処理")
  List("aaa", "bbb", "ccc")
}

println("1. ここから処理が始まる")
println(twit)

// 1. ここから処理が始まる
// 2. すごく重い初期化処理
// List(aaa, bbb, ccc)

出力の順番が変更されています。

3. 四則演算/比較/論理演算

他のプログラミング言語と同様に四則演算、論理演算が利用可能です。
加算(+)、減算(-)、乗算(*)、除算(/)、余り(%) と言った一般的な内容です。
また比較に関しても、『 == 』、『 >=』、『 >』、『 <=』、『 <』、『!』 と言ったものが利用可能です。
『&&』や『 || 』も一般的な内容です。

驚きだったのが、『i++』が使えないことです。 i に1加算は『 i = i + 1』 と定義する必要があります。
また、等価( == )の動きも意外でした。

// Int(整数型) の 変数 x を宣言  
val x : Int = 1

// 以下は動作しない!!
x++

// JavaでNGの・・・
val strHello = "Hello!"
// 以下は Trueが返される!!
if(strHello == "Hello!") true else false

Scala を勉強し始めて、最初に気に入ったところは文字列同士の比較の機能かもしれません。
Javaでは文字列同士の比較はfalse が返されます。
『String もオブジェクト ・・・。参照先が・・・・。オブジェクト指向・・・・。』 と言った内容だったかと思いますが、
文字列としては一緒だからtrueでええやん!って感じのシンプルさが好きです。

ちなみに後から出てくるオブジェクト同士の比較にもこのルールは適用されます。

// 配列みたいなもの(オブジェクト!)  
val nums = List(1, 2, 3)
// 別のオブジェクト(でも中身は "1","2","3")と比較。 結果は True
if(nums == List(1, 2, 3)) true else false

4.制御構文( if / while / foreach / for)

もう既に上で紹介しましたが、条件分岐は if で定義が可能です。Javaとかと同様に while 文も利用できます。

val greetings = List("Good Moring!","Hello!", "Bye")  
var idx = 0  
while(idx < greetings.length){
  println(greetings(idx))
  idx += 1
}
// Good Moring!
// Hello!
// Bye

while の例では配列のような変数 “greetings” をひとつづループで回して、文字列を出力している。
しかし、こちらは”greetings”のメソッドを利用して、以下のようにも表現できる。

val greetings = List("Good Moring!","Hello!", "Bye")  
greetings.foreach(greet => println(greet))  
// Good Moring!  
// Hello!  
// Bye  

恐らく Scala を勉強し始めて初めて意味が分からない表現が出てくるところである。
” greet “ って何? ” => “ って何?
とりあえず 配列のひとつひとつの要素が greet で、それを println に渡してるって事が分かってもらえれば十分な様に思える。
また、 for 文に関しては以下のように記述できる。

val greetings = List("Good Moring!","Hello!", "Bye")
for (greet <- greetings) println(greet)
// Good Moring!
// Hello!
// Bye

自分は古いJava 文化で育ったため、拡張for 文に馴染みがなく、つい初期化、条件、インクリメントに慣れてしまっていました。
Scala ではそのような面倒な記載をしなくてもコレクションをループで回す構文がシンプルにしてあります。
” <- “ こう言った『コレクションの要素をひとつづつ』と言う表現が Scalaらしいところのように感じます。

色々学習していくうちに、 if 文 と for文は 『値を返す式』 であると言う表現をみかけるようになりました。
if 文が値を返すことにまったく違和感がなかったのですが、確かにJavaとかは if で条件分岐して、処理を実行して 事前に宣言していた変数に値を設定する、 と言うことをしていたように思います。が、Scala では if 文、for 文で値を返すことができます。

var configXXX = ""
if (true)
  configXXX = "True!"
else
  configXXX = "False"
println(configXXX)
// True!

上記、記述方法ではなく、

val configYYY = if (true) "True!" else "False"  
println(configYYY)  

と言うように、if で分岐させて、値を返すということ可能になっています。
元々のJavaの考え方でいくと確かに、無駄なコードが多く、かと言って初期化のためだけに戻り値があるメソッドを新たに定義する気にもなれません。
本当にこの 『if も値を返す』と言う考え方は大事に感じます。

また、 for 文も値を返すことが出来ます!

val new_greet = for (greet <- greetings) yield greet + " Jon."
println (new_greet)
// Good Moring! Jon.
// Hello! Jon.
// Bye Jon.

この例では、 “ yeild ” と言う単語がでてきます。これも頭にすぐに入らなかったです。
1つ1つの要素の処理時に、ある特定の操作を実施してから、結果をコレクションで返せます。

上記2つの例からもわかるように、『if / forが共に値を返す』 事でソースコードの量を減らす事が可能になっています。