2012-06-06 11 views
10

Supponiamo che io sono uno stupido po 'di classe caso in questo modo:letrec in Scala? ("? Legare il nodo" via Immutabile a)

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

Come posso definire a e b immutabilmente tale che a.other è b, e b.other è a? Scala fornisce un modo per "tie the knot"? Mi piacerebbe fare qualcosa di simile:

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

possibilità

In Haskell farei questo:

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

a = Foo "a" b 
b = Foo "b" a 

Dove le associazioni a a e b sono contenute nel stessa espressione let o al livello superiore.

Oppure, senza abusare capacità letrec automagici di Haskell:

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

Nota il modello pigro, ~(a', b'), questo è importante.

+3

Mi chiedo come molti motori di ricerca sarà ora iniziare a trovare questa domanda per "matrimonio" ... –

+2

Questa domanda è più o meno un duplicato di http://stackoverflow.com/questions/7507965/instantiating-immutable-paired-objects. Inoltre, se fosse possibile con le classi dei casi, 'toString 'avrebbe recidato per sempre –

+0

@LuigiPlinge che la soluzione infetti la definizione della classe stessa. Mi piacerebbe vedere una soluzione in cui 'Foo' non è disponibile. 'toString' sarebbe infatti retrocedere per sempre. –

risposta

13

Si desidera che Foo rimanga invariato, ma la pigrizia in Scala è sul sito di dichiarazione. È impossibile che sia non rigido senza modificarlo e che lo schema indicato in Haskell funzioni solo perché Foo, non è rigoroso (ovvero, Foo "a" b non valuta immediatamente b).

In caso contrario, la soluzione è più o meno lo stesso, permettendo i cerchi necessari per ottenere tutto ciò non rigorosa:

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)) 
+1

Ah hai ragione. Definire 'data Foo = Foo {nome ::! String, altro ::! Foo}' fa sì che le soluzioni Haskell non funzionino. –

+0

Grazie per il commento "altrimenti Scala sarà sempre rivalutare". Buono a sapersi! – Madoc

Problemi correlati