北極海と北大西洋の間にある世界最大の島グリーンランド。過去1000年の間にわずか数回しか発生していないというレベルの大規模融解が、今年加速している。8月初旬には、地表近くで史上最高気温を計測。「全て溶けて流れ出さないように祈るのみだった」と、気功科学者は語る。
北極圏グリーンランドで史上最高気温を計測、氷床の融解が急加速 | Rolling Stone Japan(ローリングストーン ジャパン)
むちゃくちゃ暑いしね...地球温暖化ってやつ?
でも、なんか、
⇧ 氷河期に突入って話もあって...どうすれば?
あ、どうもボクです。地球がどうなるか分からないというのに、今日もプログラミングを学習するのであった、というわけで、Scala です。
Scala については、
⇧ 上記サイト様の記事が面白いです。
日本の Scala 界隈では、Scala忍者こと、吉田 憲治 (@xuwei_k)さんが、Scala のトップランナー的存在のようです。
GitHub にもいろいろ情報を上げてくれていらっしゃいます。
そんなわけで、Scala 環境を、前々回で作ったので、 Scala について学習していきますか~。
それでは、レッツトライ~。
Scala におけるデータ型
公式のサイトによりますと、
AnyVal
は値型に相当します。 事前に定義された9つの値型が存在し、それらDouble
、Float
、Long
、Int
、Short
、Byte
、Char
、Unit
、Boolean
は null非許容です。AnyRef
は参照型を意味します。全ての値型でない型は参照型として定義されます。Scalaでは全てのユーザー定義型はAnyRef
のサブタイプになります。 もしScalaがJava実行環境上で利用されるなら、AnyRef
は java.lang.Object
に相当します。⇧ っていう説明にある通り、大きく分けて、
- 値型
- 参照型
で分かれるという点では、Javaと似てるけど、微妙に異なる点もあると。
Any
は全ての型のスーパータイプであり、トップ型とも呼ばれます。 Anyは equals
、hashCode
、そして toString
のようないくつかの普遍的なメソッドを定義しています。 そしてAnyVal
とAnyRef
という2つの直系のサブクラスを持ちます。⇧ そう、この、Scala の Any っていう 概念は、Java には無さそうなんですよね。上記のような普遍的なメソッドは、Javaだと、java.lang.Object が担っていたような...。
それと、Javaだと、値型(プリミティブ型)のラッパークラスってあると思うんだけど(例えば、int のラッパークラスは、Integer みたいな)、Scala のAnyVal ではそのへんが無い感じですかね。
Scala と Java の関係
Java 8 で入ってきた要素って、ほとんど、Scala にインスパイアされたものらしい。
⇧ 上記サイト様が詳しいです。
なので、Java 8 から導入された関数型インターフェイス とかも、Scala でやってるような関数型プログラミングを実現したいってことが目的だったのではないかと。
そして、Scala は、「; (セミコロン)」が不要のようです。
また、Scala は、NullPointerException がほとんど起こらないような実装をしていくようでして、Nullチェックの悪夢から解放されるのだと。
ビバ!レボリューション!
何はともあれ、Scala の文法を練習(変数)
まぁ、練習していきますか。
Scala の特徴というか、関数型のプログラミングに共通なのかは分かりませんが、変数は基本的にimmutable(不変。再代入不可)で使用するという考えらしい。
変数なのに、変わらない?それって、定数ですやん?っていうツッコミは無しで。
一応、変数の定義には、
- val
immutable:再代入不可 - var
mutable:再代入可
の2つが使えるようです。 なんか、VB6とかも、変数って、val、var とかだった気が...意味合いは違うと思いますけど。
で、String型で immutable な変数を定義する場合は、
val msg: String = "Hello World"
みたいに書けると。
さらに、Scalaには「型推論」があるので(Javaでも、Java 9 からvarが導入されたので、型推論できるかと)、データ型を省略して、
val msg = "Hello World"
って書いてもOKらしい。
val は、再代入不可なんで、変数の中身を変えようとすると、
⇧ 怒られます。再代入したい場合は、var で宣言するしかないかと。もしくは、まったく違う変数名で、新しく「val msg2」みたいな変数を作ればOKらしい。
何はともあれ、Scala の文法を練習(データ型)
データ型もいろいろあるので、書き方を試してみる。
// ■整数 // Int型 val i: Int = 100 // val i = 100 //← 型推論 // Long型 val l: Long = 8888888888L // val l = 8888888888L //← 型推論 // ■浮動小数点数 // Double型 val d: Double = 1234567.8 // val d = 1234567.8 //← 型推論 // Float型 val f: Float = 1234.56F // val f = 1234.56 //← 型推論 // ■文字 // Char型 val c: Char = 'a' // val c = 'a' //← 型推論 // ■文字列 // String型 val s: String = "Oh my gosh!" // val s = "Oh my gosh!" //← 型推論 // ■論理値 var flug: Boolean = true // val flug = true //← 型推論
Long型の値の末尾にL、Float型の値の末尾にFを付けるのは、Java と同じ感じですかね。
出力がちょっと独特?
object HelloWorld { def main(args:Array[String]): Unit ={ val msg: String = "Hello World" // val msg = "Hello World" // ■整数 // Int型 val i: Int = 100 // val i = 100 //← 型推論 // Long型 val l: Long = 8888888888L // val l = 8888888888L //← 型推論 // ■浮動小数点数 // Double型 val d: Double = 1234567.8 // val d = 1234567.8 //← 型推論 // Float型 val f: Float = 1234.56F // val f = 1234.56 //← 型推論 // ■文字 // Char型 val c: Char = 'a' // val c = 'a' //← 型推論 // ■文字列 // String型 val s: String = "Oh my gosh!" // val s = "Oh my gosh!" //← 型推論 // ■論理値 var flug: Boolean = true // val flug = true //← 型推論 println(s"s: $s, i: $i, d: $d, f: $f") // println("Hello World"); } } // 出力結果→ s: Oh my gosh!, i: 100, d: 1234567.8, f: 1234.56
みたいな感じ。
フォーマット決めたり、計算とかもできるらしい。
println(f"s: $s%10s, i: ${i + 10}%-10d, d: $d%10.3f, f: $f%10.2f")
何はともあれ、Scala の文法を練習(制御構文)
Java と Scala でだいぶ異なるのが、制御構文の扱いではないかと。Scalaでは、式 というもののが存在するので、制御構文をそのまま変数に代入できるらしい。
■ if文、if式
どういうことかというと、 Javaのif文だと、
int score = 99; String result = null; if (score > 99) { result = "Oh my gosh!" } else if (score > 60) { result = "Pretty awesome" } else { result = "so fly!!" } System.out.println(result);
Scalaのif式だと、
val score: Int = 99; val result: String = if (score > 99) "Oh my gosh!" else if (score > 60) "Pretty awesome" else "so fly!!" System.out.println(result);
みたいに、変数に直に代入できると。
■switch文、match式
Java の switch文に該当するのが、Scala では、match式というものらしい。
Javaのswitch 文 だと、
String brand = "JPN"; BigDecimal tradeLimit = BigDecimal.valueOf(1000.0); Map<String, BigDecimal> currencyMap = new HashMap<>(); currencyMap.put("BTC", BigDecimal.valueOf(1097604.0)); currencyMap.put("ETH", BigDecimal.valueOf(20627.0)); if (Objects.isNull(brand)) { } else switch (brand) { case "BTC": if (tradeLimit.compareTo(Objects.nonNull(currencyMap.get("BTC")) ? currencyMap.get("BTC") : tradeLimit.add(BigDecimal.ONE)) >= 1) System.out.println("買いで"); break; case "ETH": if (tradeLimit.compareTo(Objects.nonNull(currencyMap.get("ETH")) ? currencyMap.get("ETH") : tradeLimit.add(BigDecimal.ONE)) >= 1) System.out.println("買いで"); break; case "QTUM": case "XLM": System.out.println("様子見"); break; default : break; }
みたいな感じになりますが、Scalaのmatch式では、
val brand: String = "JPN" val limit: BigDecimal = BigDecimal(1000.0) val map: Map[String, BigDecimal] = Map( "BTC" -> BigDecimal(1097604.0), "ETH" -> BigDecimal(20627.0) ) var result: String = brand match { case "BTC" if (limit.compareTo(map.getOrElse("BTC", (limit + BigDecimal(1)))) >= 1) => "買いで" case "ETH" if (limit.compareTo(map.getOrElse("ETH", (limit + BigDecimal(1)))) >= 1) => "買いで" case "QTUM" | "XLM" => "様子見" case other => s"どれにも当てはまらん...: ${other}" } println(result)
みたいな感じになるようです。
2019年8月26(月):追記 ↓ ここから
Javaでも、switch式が導入されてるらしい。
Java12でプレビューとしてswitch式が入って、Java13で正式化できるよう作業が進んでいます。 そんな中、switch式を正式化するJEPのドラフトが出ていました。
追記 あっというまにドラフトではなくなっています JEP 354: Switch Expressions
switch式の値付きbreakはbreak-withになることがほぼ確定(追記ありyieldになりました) - きしだのHatena
⇧ きしださんのブログ情報によると、Java 13 で正式に導入されたようです。
2019年8月26(月):追記 ↑ ここまで
■while文、do while文
■for文、for式
for については、だいぶ、様子が変わってきます。
Javaだと、
for (int i = 0; i <= 10; i++) { if (i == 10) { System.out.println("10カウント"); } }
みたいな感じですが、
for (i <- 0 to 10) { if (i == 10) { println("10カウント") } }
てな具合。yield っていう概念も出てくるようです。
var results = for (i <- 0 to 10; j <- 0 to 10 if i != j) yield s"$i, $j" for (el <- results) println(el)
ってな具合。
yield の ある・なしって何が違うの?ってなことについては、
⇧ 上記サイト様が詳しいです。
とりあえず、基本的なことがらについて、Scalaの学習をしてみました。Scala 特有の概念がまだ全然まとめれていないので、時間あるときにまとめていきたいですね。
少しづつ、Scalaに慣れていきたいですね。
今回はこのへんで。