Scala函数返回另一个可以在内部保存数据的函数

时间:2017-03-25 00:32:05

标签: scala function

为简单起见,我想说我想创建一个函数:

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的幂只是一个例子。我对如何实现这个想法很感兴趣?

2 个答案:

答案 0 :(得分:3)

您的描述有点混乱,但听起来您可能希望tabulate覆盖ListVector这样的集合。

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可以完成类似的事情。

变得越来越复杂

根据您的需要,tabulateiterate可能有点过于简单。也许你想通过两个输入参数进行快速查找。假设您有一个执行复杂计算的函数。如果对于任何给定的输入,输出仅计算一次并且之后变为简单的查找,那将是很好的。

// 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并相应地转换数组。