Scala函数Currying和call按名称函数,GenricTypes

问题描述 投票:0回答:3

我对scala curying和名字函数调用有点新意。我在理解语法方面遇到了困难。什么是函数的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()
    }
  }
scala function currying
3个回答
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循环的内置控制流程!


0
投票

据我所知,这是一个功能,它采取一些Table(可能是db表)并尝试使用参数scan scna这个tabel。使用相关的scanner收集数据后,此方法只是将收集的序列映射到R类型的对象。对于这种映射,它使用f函数。

你可以使用这个功能:

val list: List[Result] = withScan(table, scanner)(results => results.toList)

要么

val list: List[Result] = withScan(table, scanner)(results => ObjectWhichKeepAllData(results))

恕我直言,它编写的代码不是很好,而且我觉得更好的做法是在这个函数之外做映射。让客户端进行映射(BTW应该针对每个结果),并仅为该函数留下扫描。


0
投票

这是高阶函数的一个例子:一个将另一个函数作为参数的函数。

该函数似乎执行以下操作: - 使用传入的扫描程序打开传入的表 - 使用迭代器解析表,在本地ArrayBuffer中填充条目 - 调用由调用者传入的函数,对于条目序列,已被解析。

函数参数允许使用此功能对扫描的信息执行任何操作,具体取决于传入的函数。

同样可以声明函数原型:

def withScan[R](table: Table, scan: Scan, f: (Seq[Result]) => R): R = {

该函数已声明有两个参数列表;这是一个currying的例子。调用函数时这是一个好处,因为它允许使用更清晰的语法调用该方法。

考虑一个可能传递给这个函数的函数:

def getHighestValueEntry(results: Seq[Result]): R = {

没有currying,函数将被调用如下:

withScan[R](table, scan, results => getHighestValueEntry(results))

通过curry,可以以使功能参数更加清晰的方式调用该功能。如果你只传入一个参数,Scala能够使用花括号而不是括号来包围函数的参数,这有助于此:

withScan(table, scan) { results => 
    getHighestValueEntry(results) }
© www.soinside.com 2019 - 2024. All rights reserved.