2009年11月
2009年11月30日
1週間前の話になるが、札幌Java第17回勉強会に参加した。
Maraigue風。:JavaFXが可愛い(言語的な意味で)
以前第13回勉強会において、JavaFXに対して言語としての面白さを感じてきたが、今回扱われた言語「Scala」からも、それに近い面白さを感じられた。
ScalaはJavaFXと同様、Javaバイトコードにコンパイルされて動くコンパイル型言語である。Javaのライブラリを利用できるのもJavaFXと同様である。Scalaは、言語の基本構造は手続き的言語に属するものの、関数型言語としての性質も兼ね備えている。
私がこの勉強会で知ったのはScalaのごく一部であるものの、それでもScalaには「プログラムを書きやすくする仕掛けが多数ある」という点で面白さを感じた。この点はJavaFXも同じである。
ScalaとJavaFXを比べたとき、JavaFXもプログラムの書きやすさを考慮した記法が多数導入されているものの、JavaFXの「書きやすさ」は(JavaFXのそもそもの目的である)GUIアプリケーションの開発で強く現れるのに対し、Scalaのそれはより汎用的だと感じられた。
私がScalaの面白さを強く感じられたのは、私がRubyに慣れていた、すなわちRubyと同様に「手続き型言語ながら、関数型言語の便利な点を多数取り込んでいる」言語であることに起因しているのかもしれない。
今回の勉強会で現れた内容のうち、いくつか(Javaから見て)Scalaに特徴的なコードの例を挙げる。(資料はファイル - java-sapporo | Google グループの「JavaプログラマーのためのScala入門.pdf」にあります)
型推論
scala> var a = 5 // 型を明示した宣言 "var a:Int = 5" をしなくても…
a: Int = 5 // 自動的にIntが指定される
scala> a = 42
a: Int = 42
scala> a = "Maraigue" // 指定した型に反する代入は出来ない
<console>:5: error: type mismatch;
found : java.lang.String("Maraigue")
required: Int
a = "Maraigue"
^
メソッド定義 / クロージャ
// クロージャをリテラルの形で書く(関数リテラル)際は
// "{引数 => 内容}" という形になる
scala> var hoge = {x:Int => x * 3}
hoge: (Int) => Int = <function>
scala> hoge(42) // 変数に代入されたクロージャの呼び出し
res1: Int = 126
// メソッド定義
scala> def test(i:Int, j:Int) = i*j
test: (Int,Int)Int
// 定義されたメソッドは、「_」を付与するとクロージャとして扱える
scala> var func = test _
func: (Int, Int) =< Int = <function>
scala> func(9, 8)
res2: Int = 72
リストリテラル
scala> var int_list = List(5, 7, 8)
int_list: List[Int] = List(5, 7, 8)
// IntのListであると自動的に判断される
scala> var str_list = List("5", "7", "8")
str_list: List[java.lang.String] = List(5, 7, 8)
// java.lang.StringのListであると自動的に判断される
// mapは、リストの各要素に対して、引数として与えられた
// 関数の処理を施すメソッド。
// この場合、"i:Int => i * 3" のように "Int" を
// 付けなくても、メソッドの呼び出し元が List[Int] だと
// 分かっているので、自動的にiはIntと扱われる。
scala> int_list.map(i => i * 3)
res1: List[Int] = List(15, 21, 24)
// 同様に以下の例では、自動的にiはjava.lang.Stringと
// 扱われる。
scala> str_list.map(i => i * 3)
res2: List[String] = List(555, 777, 888)
ループ
scala> var int_list = List(5, 7, 8)
int_list: List[Int] = List(5, 7, 8)
scala> for(i <- int_list) println(i * 3)
15
21
24
// 特定の範囲の整数でループさせる方法
scala> for(i <- 1 to 3) println(i * 3)
3
6
9
// 二重ループも簡単に書ける
scala> for(i <- int_list; j <- 1 to 3){
| println("(" + i + "," + j + ")") }
(5,1)
(5,2)
(5,3)
(7,1)
(7,2)
(7,3)
(8,1)
(8,2)
(8,3)