用Scala定义循环列表的最新方法是什么? [英] What's the neatest way to define circular lists with Scala?

查看:103
本文介绍了用Scala定义循环列表的最新方法是什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是我的尝试:

case class A(val a: A, val b: Int){
    override def toString() = b.toString
}

lazy val x: A = A(y, 0)
lazy val y: A = A(z, 1)
lazy val z: A = A(x, 2)

问题在试图用x做任何事情;导致x的求值从循环求值开始,经过x,y,z,并在堆栈溢出中结束。有没有一种方法可以指定val a应该懒惰地计算?

The problem comes when trying to do anything with x; causing x to be evaluated starts off a circular evaluation going through x, y, z and ends in a stack overflow. Is there a way of specifying that val a should be computed lazily?

推荐答案

您需要使 Aa 本身很懒。
可以通过将其转换为用于初始化惰性字段的by name参数来实现:

You need to make A.a itself lazy. You can do it by turning it into a by name parameter that is used to initialize a lazy field:

class A(a0: => A, val b: Int){
  lazy val a = a0
  override def toString() = b.toString
}
object A {
  def apply( a0: => A, b: Int ) = new A( a0, b )
}

您也可以使用辅助类 Lazy

implicit class Lazy[T]( getValue: => T ) extends Proxy {
  def apply(): T = value
  lazy val value = getValue
  def self = value
}

它的优点是您的代码几乎没有变化,除了将 a:A 更改为 a:Lazy [A]

It has the advantage that you code is pretty much unchanged except for changing a: A into a: Lazy[A]:

case class A(val a: Lazy[A], val b: Int){
 override def toString() = b.toString
}

请注意访问包裹在 Lazy ,您可以使用应用(如 xa() xavalue

Note that to access the actual value wrapped in Lazy, you can either use apply or value (as in x.a() or x.a.value)

这篇关于用Scala定义循环列表的最新方法是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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