Engineer in Tokyo

Scalaの勉強

今日は Scala ハッカソン にいけなくて、せっかくなので、Scalaをちょっと勉強しようと思って、インストールしてみた。Scalaは Python, Rubyみたいに、関数型プログラミングができて、JavaのJVMの上に動く言語ので、可能性が結構広く見える。俺だって、Scalaさえあれば、Javaで頑張る気がないと思う。

基本的なところから始まるんですが、気になったところから、書いておこう。

Scalaは変数を定義する方法が二つある、val と varで定義する。定数は val で定義して、変数は var で定義する。valで定義したのを変更しようとしたらエラーがでる。

scala> val my_constant = "定数"
my_constant: java.lang.String = 定数

scala> var my_variable = "変数"
my_variable: java.lang.String = 変数

scala> my_constant = "変更"
<console>:6: error: not found: value my_constant
val synthvar$0 = my_constant;
                 ^
<console>:4: error: not found: value my_constant
       my_constant = "変更"
       ^

配列のアイテムは ()で取る。

scala> var my_list = new Array[String](3)
my_list: Array[String] = Array(null, null, null)

scala> my_list(0) = "my_list 1"

scala> my_list(1) = "my_list 2"

scala> my_list(2) = "my_list 3"

scala> my_list(1)
res4: String = my_list 2

Scalaでは、無名関数を定義することができる。pythonの lambda と似ていること。でも、無名関数を変数として、保存できないみたい。関数の引数だけに使えるみたい。

scala> my_list.foreach(value => println(value))
my_list 1
my_list 2
my_list 3

scala> my_list.foreach(value => println(value))
my_list 1
my_list 2
my_list 3

メソッドは def で定義する。引数のタイプは ‘:’ で定義しないといけないけど、返すデータのタイプは大体分かってくれる。下のリターンタイプは Intと割り出してくれた。リターン値は関数の最後の文の値になる。

scala> def my_func(value:Int) = if (value > 10) value else 10
my_func: (Int)Int

scala> my_func(123)
res6: Int = 123

scala> my_func(5)
res7: Int = 10

リターンタイプを手動で定義する場合は、こう書けばいい。引数の定義の後に、コロンを付けて、その後にリターンタイプを定義する。

scala> def my_func(value:Int): Int = if (value > 10) value else 10
my_func: (Int)Int

具体的なプログラムを書こうと思って、この間のPythonハッカソンで id:yuroyoro さんが発表してくれたscala の twitterクライアント (python ハッカソンなのになぜかscalaの話)をもとにして、atnd.orgのイベントの参加者リストを返すプログラムを作った。。

import scala.xml._
import scala.io.Source

//1627
object AtndClient {
    def main(args: Array[String]) {
        val url =
            "http://api.atnd.org/events/users/?event_id=%s".format(args.first)
        (XML.loadString(
                Source.fromURL(url, "utf-8").getLines.mkString) \\ "user"
        ).foreach(
            user =>
                println((user \\ "nickname")(0).child.text)
        )
    }
}
AtndClient.main(args)
// vim: set ts=4 sw=4 et: