Scalaの式と関数

定義
  • def x = e のような定義が評価される際には、eは評価されない
  • eはxが使われるたびに評価される
  • val x = e の定義では、eも評価される
評価
情報の専門教育を受けていない自分にとっては、整理のためにも役に立つ話が多い。
  • 先行評価はcall-by-value、遅延評価はcall-by-nameと言うらしい
  • call-by-valueは重複評価を避けられるが、無限ループを起こすケースがある
  • call-by-nameは無駄な評価を避けられ、無限ループも回避できる
最後のは、
scala> def loop: Int = loop
loop: Int
scala> def first(x: Int, y: Int) = x
first: (Int,Int)Int
こういう状況で、 first(1, loop) を呼び出す場合を考えればわかりやすい。Haskellでも良くでてきた気がする。ScalaはHaskellとは違って基本は先行評価だが、引数の型定義で「:」のかわりに「=>」 を使うことで遅延評価になる。この書式明らかに、関数だよなぁ…変数を関数化するようなイメージだろうか。いや、結局Call-by-nameにする、というのが一番わかりやすいかもしれない。こんな感じ。
scala> def constOne(x: Int, y: => Int) = 1
constOne: (Int,=> Int)Int
scala> constOne(1, loop)
unnamed0: Int = 1
scala> constOne(loop, 2) // gives an infinite loop.
Scalaいいねぇ。わくわくするわぁ…。

条件式
Javaと違い、文の選択だけではなく式の選択に使うことができる。よって、Javaの三項演算子みたいに使える。…と書いてあるけど、Rubyみたいにif~else自体が式だ(値を持つ)と言った方がいいのかもしれない。

ニュートン法による平方根の計算

このアルゴリズム自体を知りませんでした。知りたい人はWikipediaとか見た方がいいよ。面白い例なんだけど、特に新しいことが出てくるわけでもないので省略。

関数のネスト
Scalaではブロック自体が式であり、値はブロック最終行の値となるらしい。Ruby?
ブロック内のすべての定義は、セミコロンで終わらなければならないが、推測できる場合は勝手に挿入してくれるらしい。
また、外部ブロックで定義された変数・定数は内部ブロックから参照できる。

末尾再帰
末尾再帰に関するScala処理系の話。末尾再帰の場合には、書き換えが行われてスタックフレームを無駄に消費しない。末尾再帰に関してはWikipedia見た方が早い。

はー・・・意外と頑張った話が多いよ、サンプルで説明、なのにさー。例によって数学的な話が多いし。もうちょっと数学屋さんじゃなくても身近な例があるといいのに。

コメント