gpt4 book ai didi

scala - 隐式转换导致无限递归,但这不应该进行类型检查

转载 作者:行者123 更新时间:2023-12-01 02:12:47 24 4
gpt4 key购买 nike

我正在尝试为一个以 Squants 时间作为参数的类编写 Specs2 测试。诀窍在于,这两个工具都定义了一个隐式,它添加了一个名为“seconds”的方法来将数字转换为它们自己的表示形式(一种情况下是 sqants.time.Seconds,另一种情况下是 org.specs2.time.Duration),并且不幸的是,错误的似乎优先。

val a = new MyClass(10 seconds)  // doesn't build because MyClass wants a Time instead of a Duration

明确地说,我可以通过不依赖隐式来构建 Squants Time 来解决这个问题,这不是问题。

我更喜欢隐式,所以我决定添加一个隐式来将持续时间转换为时间:
implicit def specsTimeToSquantsTime(t: org.specs2.time.Duration): squants.time.Time = squants.time.Seconds(t.toSeconds)

这让它进行了类型检查,但是当我运行测试时,我得到了堆栈溢出并且堆栈跟踪没有多大意义,它说我的隐式转换正在调用自身(它不会进行类型检查,即使鉴于上面的代码,它仍然是不可能的!):
[error] package.TestConversions$.specsTimeToSquantsTime(TestConversions.scala:9)
[error] package.TestConversions$.specsTimeToSquantsTime(TestConversions.scala:9)
[error] package.TestConversions$.specsTimeToSquantsTime(TestConversions.scala:9)
...

所以我有三个问题:这里发生了什么?有一个更好的方法吗?我可以手动隐藏 Int=>Duration 隐式吗?

最佳答案

方法toSeconds定义在 Time 内类(class):

final class Time private (val value: Double) extends Quantity[Time] {    
...
def toSeconds = to(Seconds)
...
}

https://github.com/garyKeorkunian/squants/blob/master/src/main/scala/squants/time/Time.scala

因此,当编译器看到在 Duration 上调用此方法时- 它正在寻找适当的隐式,它是 specsTimeToSquantsTime ,其中包含 Duration.toSeconds反过来,这需要从 Duration 进行隐式转换至 Time等等等等。因此,您在运行时会收到无限递归调用,这从编译器方面来说是完全正确的,因为理论上您可以停止这种递归,并且没有通用的方法(请参阅 halting problem )来检测它。

NoTimeConversions 您可以在规范中混合使用特征以避免隐式转换:

This trait can be used to deactivate the time conversions (to avoid conflicts with Akka's conversions for example

关于scala - 隐式转换导致无限递归,但这不应该进行类型检查,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27906905/

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