12

次のようなばかげた小さなケース クラスがあるとします。

case class Foo(name: String, other: Foo)

is 、 is 、isなどab不変に定義するにはどうすればよいですか? scala は「結び目を作る」方法を提供していますか? 私はこのようなことをしたいと思います:a.otherbb.othera

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

可能性

Haskell では、次のようにします。

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')重要です。

4

1 に答える 1

15

変わらずにいたい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))
于 2012-06-06T03:12:57.987 に答える