gpt4 book ai didi

scala 隐式导致 StackOverflowError

转载 作者:行者123 更新时间:2023-12-04 11:26:07 27 4
gpt4 key购买 nike

这个隐式 val 如何导致 StackOverFlowError?

(削减我的原始代码,仍然导致错误)

object Complicit {
// a class with name, default, and conversion function as implicit val
case class CC[A](name: String, defaultValue: A)(implicit val convert: String => A) {
def getFrom(s: String): A= try {
convert(s)
} catch {
case t: Throwable =>
println("ERROR: %s".format(t)) // just to see the StackOverflowException
defaultValue
}
}

// this works fine
object Works {
val cc1= CC("first", 0.1)(_.toDouble)
}

// this causes java.lang.StackOverflowError due to the implicit
object Fails {
// !!! StackOverFlowError here
implicit val stringToDouble: String => Double= { _.toDouble }

val cc2= CC("second", 0.2)
}

def main(args: Array[String]) {
// this works
println("%s %f".format(Works.cc1.name, Works.cc1.getFrom("2.3")))
// this fails
println("%s %f".format(Fails.cc2.name, Fails.cc2.getFrom("4.5")))
}
}

我在用隐式做一些非法的事情吗?

最佳答案

我相信我可以回答这里发生的事情..它与其他隐式转换以及您刚刚创建的转换有关。如果添加此跟踪,您可以确认堆栈溢出通常与什么有关 - 一个函数重复调用自身,直到 java 的堆栈空间崩溃:

implicit val stringsToDouble: String => Double= { x=>println("called inner "+x); x.toDouble }

....
称为内部 4.5
称为内部 4.5
称为内部 4.5
称为内部 4.5
调用内部 4.5ERROR: java.lang.StackOverflowError

我认为正在发生的事情是这样的 - toDouble 不是 java 字符串的自然函数,而是使用 StringOps 中的隐式转换(或 StringLike,我不太确定,但这是同一个问题)。

因此,当您调用 toDouble 时,编译器开始寻找可能包含函数“toDouble”的隐式转换。理论上,它可以是任何结果类。

但是 - 如果几个隐式转换可以实现这一点,会发生什么?不幸的是,“Double”还包含函数 toDouble,正如这里所证明的:
val x = 44.4
x.toDouble

你猜怎么着?这意味着你的新隐式函数,现在最接近的范围赢得比赛,并在一个圆圈中调用 get 以完成“toDouble” - 有效地尝试将字符串转换为 double 值,以便重复调用 toDouble (在 Double 类上)。 . 我承认这相当令人困惑,但证据确凿。

这是修复..它符合解释并防止递归调用。
 implicit val stringsToDouble: String => Double= { java.lang.Double.parseDouble(_)  }

关于scala 隐式导致 StackOverflowError,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17824717/

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