結果をメモ!Scala を使用すると、必要なすべてのロジックを抽象化することさえできます。
必要なインフラストラクチャ:
scala> :paste
// Entering paste mode (ctrl-D to finish)
// A little memoization utility
object Memoization extends Memoization
trait Memoization {
trait Memoizable[A] {
def memoize(fun: A): A
}
implicit def fun1memoizable[A, B] = new Memoizable[A => B] {
def memoize(f: A => B): (A => B) = new MemoizedFunction(f)
}
implicit def fun2memoizable[A, B, C] = new Memoizable[(A, B) => C] {
def memoize(f: (A, B) => C): (A, B) => C = {
val memo = new MemoizedFunction(f.tupled)
(a, b) => memo((a, b))
}
}
implicit def fun3memoizable[A, B, C, D] = new Memoizable[(A, B, C) => D] {
def memoize(f: (A, B, C) => D): (A, B, C) => D = {
val memo = new MemoizedFunction(f.tupled)
(a, b, c) => memo((a, b, c))
}
}
def memoize[F](f: F)(implicit m: Memoizable[F]): F = m memoize f
class MemoizedFunction[-A, +B](f: A => B) extends (A => B) {
private[this] val cache = collection.mutable.Map.empty[A, B]
def apply(a: A): B = cache.getOrElseUpdate(a, f(a))
}
}
import Memoization._
// Abstracting flyweight pattern
// (http://en.wikipedia.org/wiki/Flyweight_pattern)
trait Flyweight[Args, Obj] { self: (Args => Obj) =>
val on: Args => Obj = memoize(this : (Args => Obj))
}
// Ctrl+D
使用法:
scala> :paste
// Entering paste mode (ctrl-D to finish)
case class IntegerWrapper private(i: Int) {
println(this.toString + " created.")
}
object IntegerWrapper extends (Int => IntegerWrapper)
with Flyweight[Int, IntegerWrapper]
// Ctrl+D
scala> IntegerWrapper.on(11)
IntegerWrapper(11) created.
res0: IntegerWrapper = IntegerWrapper(11)
scala> IntegerWrapper.on(11)
res1: IntegerWrapper = IntegerWrapper(11)
これは一般的な解決策であり、Map
. Vector
特定のケースではを使用したほうがよい場合があります。