Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/scala/18.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在Scala的letrec?(结为一体的不变方式)_Scala_Letrec_Tying The Knot - Fatal编程技术网

在Scala的letrec?(结为一体的不变方式)

在Scala的letrec?(结为一体的不变方式),scala,letrec,tying-the-knot,Scala,Letrec,Tying The Knot,假设我有这样一个愚蠢的小案例类: case class Foo(name: String, other: Foo) 我如何不可变地定义a和b,使得a.other是b,而b.other是a?scala是否提供了一些解决问题的方法?我想这样做: val (a, b): (Foo, Foo) = (Foo("a", b), Foo("b", a)) // Doesn't work. 可能性 在哈斯克尔,我会这样做: data Foo = Foo { name :: String, other :

假设我有这样一个愚蠢的小案例类:

case class Foo(name: String, other: Foo)
我如何不可变地定义
a
b
,使得
a.other
b
,而
b.other
a
?scala是否提供了一些解决问题的方法?我想这样做:

val (a, b): (Foo, Foo) = (Foo("a", b), Foo("b", a)) // Doesn't work.

可能性

在哈斯克尔,我会这样做:

data Foo = Foo { name :: String, other :: Foo }

a = Foo "a" b
b = Foo "b" a
其中对
a
b
的绑定包含在同一
let
表达式中,或位于顶层

或者,在不滥用Haskell的自动letrec功能的情况下:

(a, b) = fix (\ ~(a', b') -> Foo "a" b', Foo "b" a')

注意惰性模式,
~(a',b')
,这很重要。

您希望
Foo
保持不变,但Scala中的惰性在声明站点上。如果不改变它,
Foo
不可能是非严格的,Haskell中指出的模式只起作用,因为那里的
Foo
是非严格的(也就是说,
Foo“a”b
不会立即计算
b

否则,解决方案基本相同,允许使用必要的箍环,以使所有内容都不严格:

class Foo(name: String, other0: => Foo) { // Cannot be case class, because that mandates strictness
  lazy val other = other0 // otherwise Scala will always reevaluate
}
object Foo {
  def apply(name: String, other: => Foo) = new Foo(name, other)
}

val (a: Foo, b: Foo) = (Foo("a", b), Foo("b", a))

我想知道现在有多少搜索引擎会开始为“婚礼”寻找这些问题……这个问题或多或少是重复的。此外,如果可以使用case类,
toString
将递归forever@LuigiPlinge该解决方案会影响类本身的定义。我想看看
Foo
未缓存的解决方案
toString
确实会永远重复。啊,你说得对。定义
data Foo=Foo{name::!String,other::!Foo}
会导致Haskell解决方案无法工作。感谢您的评论“否则Scala将始终重新计算”。很高兴知道!