我对scala curying和name函数调用有点新意。我在理解语法方面遇到了困难。什么是函数的fllow为什么需要返回f(结果)以及进一步应用什么函数。
def withScan[R](table: Table, scan: Scan)(f: (Seq[Result]) => R): R = {
var resultScanner: ResultScanner = null
try {
resultScanner = table.getScanner(scan)
val it: util.Iterator[Result] = resultScanner.iterator()
val results: mutable.ArrayBuffer[Result] = ArrayBuffer()
while (it.hasNext) {
results += it.next()
}
f(results)
} finally {
if (resultScanner != null)
resultScanner.close()
}
}
答案 0 :(得分:1)
让我们看一下函数签名
def withScan[R](table: Table, scan: Scan)(f: (Seq[Result]) => R): R
首先,忽略现在花哨的currying语法,因为你总是可以通过将所有参数放在一个参数列表中来将curried函数重写为普通函数,即
def withScan[R](table: Table, scan: Scan, f: Seq[Result] => R): R
其次,注意最后一个参数是一个函数,我们不知道它到底做了什么。 withScan
将采用某人提供的函数并在某些事物上使用该函数。我们可能会对为什么有人需要这样的功能感兴趣。由于我们需要处理大量需要正确打开和关闭的资源,例如File,DatabaseConnection,Socket,......然后我们将重复使用关闭资源的代码,甚至更糟糕的是,忘记关闭资源。因此,我们希望将无聊的公共代码考虑在内以便为您提供方便的功能:如果您使用withScan
访问该表,我们将以某种方式为您提供Result
,以便您可以对此进行操作我们将确保为您正确关闭资源,以便您可以专注于有趣的操作。这称为“贷款模式”
现在让我们回到讨论语法。虽然currying有其他有趣的用例,我相信它是用这种风格编写的原因是在Scala中,你可以使用花括号块将参数传递给函数,即可以像上面这样使用上面的函数
withScan(myTable, myScan) { results =>
//do whatever you want with the results
}
这看起来就像内置的控制流,如if-else或for循环!
答案 1 :(得分:0)
据我所知,正确的是这个函数需要一些Table
(可能是db表)并尝试使用参数scan
来搜索这个表格。使用相关scanner
此方法收集数据后,只需将收集的序列映射到R
类型的对象。
对于此类映射,使用f
函数。
您可以使用此功能:
val list: List[Result] = withScan(table, scanner)(results => results.toList)
或者
val list: List[Result] = withScan(table, scanner)(results => ObjectWhichKeepAllData(results))
恕我直言,它编写的代码不是很好,而且我觉得更好的做法是在这个函数之外做映射。让客户端进行映射(BTW应该针对每个结果),并仅为该函数留下扫描。
答案 2 :(得分:0)
这是高阶函数的一个例子:一个将另一个函数作为参数的函数。
该功能似乎执行以下操作: - 使用传入的扫描程序打开传入的表 - 使用迭代器解析表,填充本地ArrayBuffer中的条目 - 调用由调用者传入的函数,对已解析的条目序列进行调用。
函数参数允许使用此功能对扫描的信息执行任何操作,具体取决于传入的函数。
函数原型同样可以声明:
def withScan[R](table: Table, scan: Scan, f: (Seq[Result]) => R): R = {
该函数已声明有两个参数列表;这是一个currying的例子。调用函数时这是一个好处,因为它允许使用更清晰的语法调用该方法。
考虑一个可能传递给这个函数的函数:
def getHighestValueEntry(results: Seq[Result]): R = {
如果没有curry,函数将被调用如下:
withScan[R](table, scan, results => getHighestValueEntry(results))
通过curry,可以调用函数,使函数参数更加清晰。如果你只传递一个参数,Scala能够使用花括号而不是括号来包围函数的参数,这有助于此:
withScan(table, scan) { results =>
getHighestValueEntry(results) }