为简单起见,我想说我想创建一个函数:
def powerOfTwo(n: Int): Int => Int
输出是另一个函数,可以这样使用outputFunction(x)给我2 ^ x。
n: Int
表示从1到n的2的幂范围,即{2^1, 2^2, ... 2^n}
。我希望预先计算这些值,以便通过简单的查找可以使用结果函数Int => Int
来获得该权力数组2的相应元素。
我想知道如何实现这一目标?我应该创建一个Class
,然后我用它来初始化一些内部var
对象,然后传递一个函数,该函数将输出该var
个对象的相应元素吗?
希望这很清楚。请注意,2的幂只是一个例子。我对如何实现这个想法很感兴趣?
答案 0 :(得分:3)
您的描述有点混乱,但听起来您可能希望tabulate
覆盖List
或Vector
这样的集合。
def powerOfTwo(n: Int) = List.tabulate(n)(math.pow(2,_))
现在您可以获得指定数量的预先计算的2次幂。
val firstTen = powerOfTwo(10)
并根据需要访问计算值。
firstTen(7) // res0: Double = 128.0
如果每个值的计算特别昂贵,那么您可能希望使用Stream.tabulate
,因为每个元素只会根据需要计算,但结果会被缓存(memoized),并且可以重复引用而无需重新计算。
使用List.iterate
可以完成类似的事情。
变得越来越复杂
根据您的需要,tabulate
或iterate
可能有点过于简单。也许你想通过两个输入参数进行快速查找。假设您有一个执行复杂计算的函数。如果对于任何给定的输入,输出仅计算一次并且之后变为简单的查找,那将是很好的。
// memoize a function of arity 2
def memo[A,B,R](f: (A,B)=>R): ((A,B)=>R) = {
val cache = new collection.mutable.WeakHashMap[(A,B),R]
(a:A,b:B) => cache.getOrElseUpdate((a,b),f(a,b))
}
现在你可以记住一些艰难计算的输出。
def toughCalc(b: Boolean, n: Double) = { ....
val toughCalcMemo = memo(toughCalc)
toughCalcMemo(true, 44.3) // initial calculation
toughCalcMemo(false, 34.4) // initial calculation
toughCalcMemo(true, 44.3) // simple lookup
答案 1 :(得分:1)
scala中的函数可以记住值。这也被称为“封闭”。 因此你可以写下例如。
def powerOfTwo(n: Int): Int => Int = {
val arr = Array.iterate(1,n+1)(_*2)
i => arr(i)
}
然而,有一种更简单的方法,因为Scala可以自动将许多集合类型(如Array,Vector,List等)转换为函数。这意味着你可以在一行中写这个
def powerOfTwo(n: Int): Int => Int = Array.iterate(1,n+1)(_*2)
Scala看到期望的类型为Int => Int
并相应地转换数组。