隐式使用Scala的Predef时如何防止堆栈溢出 [英] How to prevent stack overflow when using Scala's Predef.implicitly

查看:95
本文介绍了隐式使用Scala的Predef时如何防止堆栈溢出的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

鉴于这个简单的代码片段,我很惊讶地激起了堆栈溢出的简单过程:

Given this simple code snippet I am astounded to provoke a stack overflow this easy:

implicit def foobar: Unit = implicitly[Unit]

在更复杂的用例中,我有以下情形:

In my little more complex use case I have the following situtation:

abstract class Foo {
  type Repr_Tpe
  protected implicit def repr2Ordered: Repr_Tpe => Ordered[Repr_Tpe]
}

class Bar extends Foo {
  type Repr_Tpe = Long
  protected implicit def repr2Ordered = implicitly[Repr_Tpe => Ordered[Repr_Tpe]]
}

在类Foo中定义方法repr2Ordered无效,因为类型Repr_Tpe是抽象的.因此,我决定复制&粘贴声明并从中进行定义; 显然从上面导致堆栈溢出.只有从类Bar中的定义中删除修饰符implicit才能解决此问题.

Defining method repr2Ordered in class Foo does not work because type Repr_Tpe is abstract. So I decided to copy & paste the declaration and make a definition out of it; apparently leading to the stack overflow from above. Only by removing the modifier implicit from the definition in class Bar solves this problem.

难道没有一个巧妙的解决方案可以避免这种陷阱吗?

Isn't there an elegant solution circumventing this pitfall?

推荐答案

您已将foobar定义为 be 类型为Unit的隐式值.然后,将其定义为 类型为Unit的隐式值.这样想:

You've defined foobar to be the implicit value of type Unit. Then you've defined it as the implicit value of type Unit. Thinking of it this way:

implicit def foobar: Unit = implicitly[Unit]
// you've defined foobar as the implicit value for Unit.
// so implicitly[Unit] is the same as calling foobar
// which is the same as:
implicit def foobar: Unit = foobar

与下面的语句相比,您不会感到惊讶的是,这会引起堆栈溢出:

You should be no more surprised that this causes a stack overflow than you would be by this statement:

def tharSheBlows: Unit = tharSheBlows

对于更优雅的东西,我会使用

For something with a bit more elegance, I would use a view bound to ensure that the type paramater is Ordered instead.

scala> abstract class Foo[Repr_Tpe <% Ordered[Repr_Tpe]] {}
defined class Foo

scala> class Bar extends Foo[Long] {}
defined class Bar

scala> case class Unordered(data: String)
defined class Unordered

scala> class Bam extends Foo[Unordered] {}
<console>:10: error: No implicit view available from Unordered => Ordered[Unordered].
       class Bam extends Foo[Unordered] {}
                 ^

scala> implicit def bringOrder(u: Unordered) = new Ordered[Unordered] { def compare(that: Unordered) = u.data.compareTo(that.data) }
bringOrder: (u: Unordered)java.lang.Object with Ordered[Unordered]

scala> class Bam extends Foo[Unordered] {}
defined class Bam

这篇关于隐式使用Scala的Predef时如何防止堆栈溢出的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆