2012年1月27日金曜日

mapBetween関数Scala版

dankogai先生の投稿 algorithm - mapBetween - 配列の隣接する2項にそれぞれ演算を施した配列 にあるmapBetween関数をScalaで書いてみる。
クラスを拡張する形で書きたかったのだが、いっぺんにやろうとするときっとこんがらがるのでとりあえずSeqを引数で受ける形で実装。

object MapBetween {
def main(args:Array[String]) = {
val range = 1 to 10
println(mapBetween(range, (a1:Int,a2:Int)=>a1+a2))
println(mapBetween(range, (a1:Int,a2:Int)=>a1*a2))
println(mapBetween(range, (a1:Int,a2:Int)=>a1-a2))
}
def mapBetween[A,B,T>:A](seq:Seq[A], f:(T,T)=>B): Seq[B] = {
((Seq[B](), seq.head) /: seq.tail) {(tup:(Seq[B], A), a:A) => (tup._1 :+ f(tup._2, a), a)}._1
}
}

とりあえず動くけど、果たして効率の良い実装になっているのか。。。
隣り合う2項に適用する関数のパラメタに、型を指定しなければコンパイルが通らない。第1引数Seqの型パラメタから推論して欲しいところだけどどうもそうはならないみたい。
foldLeftの左項のタプルの1つめの要素で、Seq[B]()の代わりにNilを指定したかったのだが、型の不一致でこれもまたコンパイルが通らない。まぁこちらはなんとなく仕方がない気がする。