はじめに
下記のテキストを通して、基本的な書き方を学びつつ、個人的に気になったことを検証していくメモ代わりです。
https://dwango.github.io/scala_text/basic.html
本当にありがとう、dwango様・・・
Scalaの制御構文
ざっくりまとめ
- 「構文」と「式」と「文」それぞれ使い分けよう
-
{}
式は基本中の基本 - if式、whileはCやPHPと同様の使用感
- for分はifを中にぶっこめたり、yieldにより四季を生成できる
「構文」と「式」と「文」という用語
(今まで気にしていなかった)各種用語にかんして、ざっくりまとめ
- 構文(Syntax)
- プログラミング言語内で特別扱いされるキーワードと正しいプログラムを構成するためのルール
- 式(Expression)
- 評価することで値になるもの
-
1
,1 + 2
,"hoge"
- 文(Statement)
- 評価しても値にならないもの(定義全体としては値を持たないもの)
val i:Int = 1
{}
式
-
一般系
{ exp1; exp2; ... expN }
- 式が改行で区切られていれば
セミコロンを省略可
- 式が改行で区切られていれば
-
Scalaではメソッド定義が一般的
def foo(): String = { "foo" + "foo" }
- メソッド定義の構文に特別に
{}
が含まれているわけではない-
{"foo" + "foo"}
という式が、メソッドに代入されているってことかな? ## if式
-
- メソッド定義の構文に特別に
-
一般式
if (条件式) A [else B]
-
使用方法
scala> var age = 26 age: Int = 26 scala> if (age < 20) { | "未成年" | } else { | "年がどんどん・・・" | } res1: String = 年がどんどん・・・ scala> if (age < 20) {}
while式
-
一般式
while (条件式) A
-
使用方法
scala> var i = 1 i: Int = 1 scala> while (i <= 10) { | print( i + ", ") | i++ | } <console>:11: error: value ++ is not a member of Int i++ ^ scala> while (i <= 10) { | print( i + ", ") | i += 1 | } 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
- インクリメント演算子が使えないんだという発見w
for式
-
一般式
for(ジェネレータ1; ジェネレータ2; ... ジェネレータn) A # ジェネレータ1 = a1 <- exp1; ジェネレータ2 = a2 <- exp2; ... ジェネレータn = an <- expn
-
使用方法
-
通常
scala> for (x <- 1 to 5; y <- 1 until 5) { | print( "(" + x + "," + y + ") ") | } (1,1) (1,2) (1,3) (1,4) (2,1) (2,2) (2,3) (2,4) (3,1) (3,2) (3,3) (3,4) (4,1) (4,2) (4,3) (4,4) (5,1) (5,2) (5,3) (5,4)
- 前述したジェネレータが内部にネストしたループのように扱われる
- 多重ループ書く時にネストが深くならなくて使いやすそうと思った
- 前述したジェネレータが内部にネストしたループのように扱われる
-
if有りの使用方法
scala> for (x <- 1 to 5; y <- 1 until 5 if x != y) { | print( "(" + x + "," + y + ") ") | } (1,2) (1,3) (1,4) (2,1) (2,3) (2,4) (3,1) (3,2) (3,4) (4,1) (4,2) (4,3) (5,1) (5,2) (5,3) (5,4)
- 条件式も後述できる
-
ifが中間のジェネレータの場合
scala> for (x <- 1 to 5; y <- 1 until 5 if x != y; z <- 3 to 8) { | print( "(" + x + "," + y + "," + z +") ") | } (1,2,3) (1,2,4) (1,2,5) (1,2,6) (1,2,7) (1,2,8) (1,3,3) (1,3,4) (1,3,5) (1,3,6) (1,3,7) (1,3,8) (1,4,3) (1,4,4) (1,4,5) (1,4,6) (1,4,7) (1,4,8) (2,1,3) (2,1,4) (2,1,5) (2,1,6) (2,1,7) (2,1,8) (2,3,3) (2,3,4) (2,3,5) (2,3,6) (2,3,7) (2,3,8) (2,4,3) (2,4,4) (2,4,5) (2,4,6) (2,4,7) (2,4,8) (3,1,3) (3,1,4) (3,1,5) (3,1,6) (3,1,7) (3,1,8) (3,2,3) (3,2,4) (3,2,5) (3,2,6) (3,2,7) (3,2,8) (3,4,3) (3,4,4) (3,4,5) (3,4,6) (3,4,7) (3,4,8) (4,1,3) (4,1,4) (4,1,5) (4,1,6) (4,1,7) (4,1,8) (4,2,3) (4,2,4) (4,2,5) (4,2,6) (4,2,7) (4,2,8) (4,3,3) (4,3,4) (4,3,5) (4,3,6) (4,3,7) (4,3,8) (5,1,3) (5,1,4) (5,1,5) (5,1,6) (5,1,7) (5,1,8) (5,2,3) (5,2,4) (5,2,5) (5,2,6) (5,2,7) (5,2,8) (5,3,3) (5,3,4) (5,3,5) (5,3,6) (5,3,7) (5,3,8) (5,4,3) (5,4,4) (5,4,5) (5,4,6) (5,4,7) (5,4,8)
- 記述可能
-
定義されてなくて、きっとだめだろうと思うやつ
scala> for (x <- 1 to 5 if x != y; y <- 1 until 5; z <- 3 to 8) { | print( "(" + x + "," + y + "," + z +") ") | } <console>:8: error: not found: value y for (x <- 1 to 5 if x != y; y <- 1 until 5; z <- 3 to 8) { ^
- ですよね
-
Listを使用した出力
scala> for(e <- List("A", "B", "C", "D", "E")) println(e) A B C D E scala> for(e <- List("A", "B", "C", "D", "E")) print(e + ", ") A, B, C, D, E,
-
yieldを使用
scala> for(e <- List("A", "B", "C", "D", "E")) yield { | "Pre" + e | } res8: List[String] = List(PreA, PreB, PreC, PreD, PreE)
- yield:産する、もたらす、生む、引き起こす
- コレクションの要素を加工して返す(新規に生成してくれるやつ)
-
数値の場合はどうなる?
scala> for (x <- 1 to 5; y <- 1 until 5) yield { | x + "," + y | } res9: scala.collection.immutable.IndexedSeq[String] = Vector(1,1, 1,2, 1,3, 1,4, 2,1, 2,2, 2,3, 2,4, 3,1, 3,2, 3,3, 3,4, 4,1, 4,2, 4,3, 4,4, 5,1, 5,2, 5,3, 5,4) scala> for (x <- 1 to 5; y <- 1 until 5) yield { | x + y | } res10: scala.collection.immutable.IndexedSeq[Int] = Vector(2, 3, 4, 5, 3, 4, 5, 6, 4, 5, 6, 7, 5, 6, 7, 8, 6, 7, 8, 9)
- 普遍のcollectionで返してくれる
- 型は自動生成される
- でも、vectorだから、自分で定義できないのかな?
- 調査した感じ、ジェネレータの型で自動で変換するらしいので、型はジェネレータで指定が無難?
-
とりあえず、ジェネレータで色々試す
scala> for (x <- List(1 to 5); y <- 1 until 5) yield { | x + y | } <console>:9: error: type mismatch; found : Int required: String x + y ^ scala> for (x <- List(1 to 5); y <- List(1 until 5)) yield { | x + y | } <console>:9: error: type mismatch; found : scala.collection.immutable.Range required: String x + y ^ scala> for (x <- List(1 to 5); y <- List(1 to 5)) yield { | x + y | } <console>:9: error: type mismatch; found : scala.collection.immutable.Range.Inclusive required: String x + y ^ scala> for (x <- List(1 to 5); y <- List(1 to 5)) yield { | x + "," + y | } res15: List[String] = List(Range(1, 2, 3, 4, 5),Range(1, 2, 3, 4, 5)) scala> for (x <- List(1,2,3); y <- List(4,5,6)) yield { | x + y | } res16: List[Int] = List(5, 6, 7, 6, 7, 8, 7, 8, 9) scala> for (x <- List(1,2,3); y <- List(4,5,6)) yield { | x + "," + y | } res17: List[String] = List(1,4, 1,5, 1,6, 2,4, 2,5, 2,6, 3,4, 3,5, 3,6)
- toやuntilを使用すると、Range型になるので、直接的な結合は変換後じゃないと難しそう
- 今後、型変換に関して学んだ上で追記したいところ
- toやuntilを使用すると、Range型になるので、直接的な結合は変換後じゃないと難しそう
-