gpt4 book ai didi

scala - 我们可以有一组按名称参数的函数吗?

转载 作者:行者123 更新时间:2023-12-04 16:31:25 28 4
gpt4 key购买 nike

在 Scala 中我们有一个可以写的名字参数

def foo[T](f: => T):T = {
f // invokes f
}
// use as:
foo(println("hello"))

我现在想对一组方法做同样的事情,也就是说我想将它们用作:

def foo[T](f:Array[ => T]):T = {     // does not work
f(0) // invokes f(0) // does not work
}
foo(println("hi"), println("hello")) // does not work

有什么办法可以做我想做的事吗?我想到的最好的是:

def foo[T](f:() => T *):T = {
f(0)() // invokes f(0)
}
// use as:
foo(() => println("hi"), () => println("hello"))

def foo[T](f:Array[() => T]):T = { 
f(0)() // invokes f(0)
}
// use as:
foo(Array(() => println("hi"), () => println("hello")))

编辑:Seth Tisue 在对 this answer 的评论中指出,提议的 SIP-24 不是很有用.

这会产生问题的示例是实用函数 trycatch 的以下代码:

type unitToT[T] = ()=>T
def trycatch[T](list:unitToT[T] *):T = list.size match {
case i if i > 1 =>
try list.head()
catch { case t:Any => trycatch(list.tail: _*) }
case 1 => list(0)()
case _ => throw new Exception("call list must be non-empty")
}

此处 trycatch 获取类型为 ()=>T 的方法列表,并依次应用每个元素,直到成功或到达末尾。

现在假设我有两种方法:

def getYahooRate(currencyA:String, currencyB:String):Double = ???

def getGoogleRate(currencyA:String, currencyB:String):Double = ???

将一个单位的 currencyA 转换为 currencyB 并输出 Double

我将 trycatch 用作:

val usdEuroRate = trycatch(() => getYahooRate("USD", "EUR"), 
() => getGoogleRate("USD", "EUR"))

我更愿意:

val usdEuroRate = trycatch(getYahooRate("USD", "EUR"), 
getGoogleRate("USD", "EUR")) // does not work

在上面的示例中,我希望仅在 getYahooRate("USD", "EUR") 时调用 getGoogleRate("USD", "EUR")抛出异常。这不是 SIP-24 的预期行为。

最佳答案

Here是一个解决方案,尽管与直接按名称调用相比有一些限制:

import scala.util.control.NonFatal


object Main extends App {
implicit class Attempt[+A](f: => A) {
def apply(): A = f
}

def tryCatch[T](attempts: Attempt[T]*): T = attempts.toList match {
case a :: b :: rest =>
try a()
catch {
case NonFatal(e) =>
tryCatch(b :: rest: _*)
}
case a :: Nil =>
a()
case Nil => throw new Exception("call list must be non-empty")
}

def a = println("Hi")
def b: Unit = sys.error("one")
def c = println("bye")
tryCatch(a, b, c)

def d: Int = sys.error("two")
def e = { println("here"); 45 }
def f = println("not here")

val result = tryCatch(d, e, f)

println("Result is " + result)
}

限制是:

  1. 使用 block 作为参数是行不通的;只有 block 的最后一个表达式将被包装在 Attempt 中。
  2. 如果表达式的类型为 Nothing(例如,如果 bd 未注释),则转换为 未插入 Attempt,因为 Nothing 是每个类型的子类型,包括 Attempt。大概同样适用于 Null 类型的表达式。

关于scala - 我们可以有一组按名称参数的函数吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32917373/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com