はじめに
N予備校で「Scala応用」コースを受講しています。
ストリーム
Stream
は 2.13
以降のバージョンでは非推奨になってい流ので、LazyList
を使うこと。
先頭の要素 head
と その後ろの要素 tail
で構成されるコンスで表現される。
val s = 1 #:: 2 #:: 3 #:: 4 #:: Stream.empty
// => Stream(1, ?)
最初の値は判明しているが、その後ろに何が入っているかはわからない。添字でのアクセスは可能。
無限ストリーム
val eights: Stream[Int] = 8 #:: eights
再帰的に 8 を延々と追加する。
添字でどこを取り出しても 8 が返る。
等差数列
val s = Stream.iterate(1){
n =>
println("Calculate! 3 + " + n)
3 + n
}
// s(1) => 1
// s(2) => 4
// s(3) => 7
実際に評価することで そこまでの再帰呼び出しのデータを生成する仕組みを「余再帰」という。
// 1回目の呼び出し
s(10) => 3 + 1, 3 + 4,......
// 2回目以降
s(10) => 31
途中の計算結果も含め全ての計算結果がストリームの中で保持されている。
lazyキーワード
一度値が評価取得されると、二度目は前の結果を使い回す。
実際の使い所は迷いそう。
implicit キーワード
同じスコープの別の場所で宣言をしておけば コードの実行箇所では宣言しなくても、型変換や引数への代入処理を 自動的に行ってくれる。
import scala.language.implicitConversions
implicit def intToBoolean(arg: Int): Boolean = arg != 0
数値型をBoolean型に暗黙的に変換する。
if(1) println("1はTrueだよ")
implicit def メソッド名(引数名: 引数の型): 返り値の型 = 本体
このメソッドの引数の型の式が現れた時に、 返り値の型を暗黙の候補として登録できる。
文字列の最後に:-)
を追加するメソッド
class RichString(val src: String) {
def smile: String = src + ":-)"
}
implicit def enrichString(arg: String): RichString = new RichString(arg)
// 呼び出し
"Hi, ".smile
// => Hi, :-)
既存のクラスを拡張したように見せかけることができる。
引数の省略
object HTTTravel {
class Travel {
def AzuCat(HTT: String): Unit = println(s"${HTT}、アズキャットいて。")
}
def member(name: String)(implicit travel: Travel): Unit = travel.AzuCat(name)
}
// 呼び出し
implicit val HTT = new HTTTravel.Travel
HTTTravel.member("あずにゃん")
なんかもっとうまい例が書けたらよかった
まとめ
lazy
やimplicit
について、言いたいことはわかるけれどいざ書けって言われるとちょっと自信がない。