interface MyFunctor<A> {
fun myMap<B>(f: (A) -> B): MyFunctor<B>
}
class MyFunctorList<A>(val list: List<A>) : MyFunctor<A>, List<A> by list {
override fun myMap<B>(f: (A) -> B): MyFunctor<B>
= MyFunctorList(list.map(f))
override fun toString() = list.toString()
}
fun <A> List<A>.asFunctor(): MyFunctorList<A>
= MyFunctorList(this)
fun main(args: Array<String>) {
println(arrayListOf(1, 2, 3, 4, 5).asFunctor().myMap { n -> n * 3 })
}
もし上記と同じ内容を Scala で示すなら以下のようになります。
trait MyFunctor[A] {
def myMap[B](f: A => B): MyFunctor[B]
}
class MyFunctorList[A](list: List[A]) extends MyFunctor[A] {
def myMap[B](f: A => B): MyFunctor[B]
= MyFunctorList(list.map(f))
override def toString = list.toString
}
implicit class ListOps[A](list: List[A]) {
def asFunctor: MyFunctorList[A] = new MyFunctorList(list)
}
def main(args: Array[String]) {
println(List(1, 2, 3, 4, 5).asFunctor.myMap { _ * 3 })
}
ただ、これでは myMap
が返す値が MyFunctor[B]
のため、List[B]
を取り出したりすることができません。
またスライドで最初にあげたScalaコードとは意味合いが異なります。
資料の中で「implicitだらけでScala怖い」と表現した件については、今でも可読性に難のある機能だと感じています。
とありますが、同等のコードでは implicit 1個しか出てきません。
もちろん implicit を使って可読性に難のあるコードを書くことは出来ますが、上記比較をもって「implicitだらけで可読性に難のある」と主張するには暴論のように思えます。