Letrec ในสกาล่า? (วิธีการผูกปมที่ไม่เปลี่ยนรูป?)

สมมติว่าฉันมีคลาสเคสเล็ก ๆ ที่โง่เขลาเช่นนี้:

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

ฉันจะกำหนด a และ b โดยไม่เปลี่ยนรูปได้อย่างไรว่า a.other คือ b และ b.other คือ a สกาล่ามีวิธี "ผูกปม" หรือไม่ ฉันต้องการทำสิ่งนี้:

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 เดียวกัน หรือที่ระดับบนสุด

หรือโดยไม่ใช้ความสามารถ Letrec อัตโนมัติของ Haskell ในทางที่ผิด:

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

สังเกตรูปแบบที่ขี้เกียจ ~(a', b') นั่นสำคัญ


person Dan Burton    schedule 06.06.2012    source แหล่งที่มา
comment
ฉันสงสัยว่าตอนนี้มีกี่เครื่องมือค้นหาที่จะเริ่มค้นหาคำถามนี้สำหรับงานแต่งงาน...   -  person    schedule 06.06.2012
comment
คำถามนี้ซ้ำกับ stackoverflow.com/questions/7507965 ไม่มากก็น้อย /. นอกจากนี้ หากเป็นไปได้ด้วยคลาสเคส toString จะถูกเรียกซ้ำตลอดไป   -  person Luigi Plinge    schedule 06.06.2012
comment
@LuigiPlinge โซลูชันนั้นทำให้คำจำกัดความของคลาสนั้นติดไวรัส ฉันต้องการดูวิธีแก้ปัญหาโดยที่ Foo ไม่มีการเปลี่ยนแปลง toString จะขอคืนตลอดไปอย่างแน่นอน   -  person Dan Burton    schedule 06.06.2012


คำตอบ (1)


คุณต้องการให้ 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))
person Daniel C. Sobral    schedule 06.06.2012
comment
อ่าคุณพูดถูก การกำหนด data Foo = Foo { name :: !String, other :: !Foo } ทำให้โซลูชัน Haskell ไม่ทำงาน - person Dan Burton; 06.06.2012
comment
ขอบคุณสำหรับความคิดเห็น มิฉะนั้นสกาล่าจะประเมินใหม่เสมอ เป็นเรื่องน่ารู้! - person Madoc; 06.06.2012