Библиотека
Использование Scalaz scalaz.Memo
Руководство
Ниже приведено решение, аналогичное ответу Аарона Новструпа и этого блога , за исключением некоторыхисправления / улучшения, краткость и упрощение потребностей пользователей в копировании и вставке:)
import scala.Predef._
class Memoized[-T, +R](f: T => R) extends (T => R) {
import scala.collection.mutable
private[this] val vals = mutable.Map.empty[T, R]
def apply(x: T): R = vals.getOrElse(x, {
val y = f(x)
vals += ((x, y))
y
})
}
// TODO Use macros
// See si9n.com/treehugger/
// http://stackoverflow.com/questions/11400705/code-generation-with-scala
object Tupler {
implicit def t0t[R]: (() => R) => (Unit) => R = (f: () => R) => (_: Unit) => f()
implicit def t1t[T, R]: ((T) => R) => (T) => R = identity
implicit def t2t[T1, T2, R]: ((T1, T2) => R) => ((T1, T2)) => R = (_: (T1, T2) => R).tupled
implicit def t3t[T1, T2, T3, R]: ((T1, T2, T3) => R) => ((T1, T2, T3)) => R = (_: (T1, T2, T3) => R).tupled
implicit def t0u[R]: ((Unit) => R) => () => R = (f: Unit => R) => () => f(())
implicit def t1u[T, R]: ((T) => R) => (T) => R = identity
implicit def t2u[T1, T2, R]: (((T1, T2)) => R) => ((T1, T2) => R) = Function.untupled[T1, T2, R]
implicit def t3u[T1, T2, T3, R]: (((T1, T2, T3)) => R) => ((T1, T2, T3) => R) = Function.untupled[T1, T2, T3, R]
}
object Memoize {
final def apply[T, R, F](f: F)(implicit tupled: F => (T => R), untupled: (T => R) => F): F =
untupled(new Memoized(tupled(f)))
//I haven't yet made the implicit tupling magic for this yet
def recursive[T, R](f: (T, T => R) => R) = {
var yf: T => R = null
yf = Memoize(f(_, yf))
yf
}
}
object ExampleMemoize extends App {
val facMemoizable: (BigInt, BigInt => BigInt) => BigInt = (n: BigInt, f: BigInt => BigInt) => {
if (n == 0) 1
else n * f(n - 1)
}
val facMemoized = Memoize1.recursive(facMemoizable)
override def main(args: Array[String]) {
def myMethod(s: Int, i: Int, d: Double): Double = {
println("myMethod ran")
s + i + d
}
val myMethodMemoizedFunction: (Int, Int, Double) => Double = Memoize(myMethod _)
def myMethodMemoized(s: Int, i: Int, d: Double): Double = myMethodMemoizedFunction(s, i, d)
println("myMemoizedMethod(10, 5, 2.2) = " + myMethodMemoized(10, 5, 2.2))
println("myMemoizedMethod(10, 5, 2.2) = " + myMethodMemoized(10, 5, 2.2))
println("myMemoizedMethod(5, 5, 2.2) = " + myMethodMemoized(5, 5, 2.2))
println("myMemoizedMethod(5, 5, 2.2) = " + myMethodMemoized(5, 5, 2.2))
val myFunctionMemoized: (Int, Int, Double) => Double = Memoize((s: Int, i: Int, d: Double) => {
println("myFunction ran")
s * i + d + 3
})
println("myFunctionMemoized(10, 5, 2.2) = " + myFunctionMemoized(10, 5, 2.2))
println("myFunctionMemoized(10, 5, 2.2) = " + myFunctionMemoized(10, 5, 2.2))
println("myFunctionMemoized(7, 6, 3.2) = " + myFunctionMemoized(7, 6, 3.2))
println("myFunctionMemoized(7, 6, 3.2) = " + myFunctionMemoized(7, 6, 3.2))
}
}
Когда вы запустите ExampleMemoize, вы получите:
myMethod ran
myMemoizedMethod(10, 5, 2.2) = 17.2
myMemoizedMethod(10, 5, 2.2) = 17.2
myMethod ran
myMemoizedMethod(5, 5, 2.2) = 12.2
myMemoizedMethod(5, 5, 2.2) = 12.2
myFunction ran
myFunctionMemoized(10, 5, 2.2) = 55.2
myFunctionMemoized(10, 5, 2.2) = 55.2
myFunction ran
myFunctionMemoized(7, 6, 3.2) = 48.2
myFunctionMemoized(7, 6, 3.2) = 48.2