2012-02-04 15 views
9

Lo más cercano aEn actual Scala, ¿hay una manera más clara para hacer el "patrón constructor perezoso"

case class Foo(lazy next: Foo) 

que he podido llegar a se

class Foo(_next: =>Foo) { 
    lazy val next = _next 
} 
object Foo { 
    def apply(next: =>Foo) = new Foo(next) 
    def unapply(foo: Foo) = Some(foo.next) 
} 

He encontrado un número de la lista add lazy parameters así que supongo que se agregará algún día. Mientras tanto, ¿alguien sabe un truco más limpio que el anterior?

+0

Vale la pena mencionar que el método 'unapply' no es perezoso, lo que tratar de patrón que coincida con un' 'foo' en otro foo' resultará en' next' siendo evaluado, lo cual puede que no desee. –

+0

@BrianMcCutchon Ese es un buen punto. Supongo que la única manera de hacerlo perezoso sería agregar direccionamiento indirecto, como en 'def unapply (foo: Foo) = Some (() => foo.next) '? – Owen

+0

Eso parece funcionar. Solo estaba evitando usar 'unapply' para mis clases de casos perezosa. En ese caso, sin embargo, debe llamar explícitamente a la función, como 'case Foo (n) => Foo (doSomething (n()))'. En ese momento, podría ser mejor usar 'Need'. (Además, si vas a la ruta 'Need', puedes definir un constructor sobrecargado para' Foo' que toma un parámetro call-by-name y lo convierte en 'Need'.) –

Respuesta

6

Tal vez scalaz.Need? Esto me fue sugerido en this answer.

scala> case class Foo(next: Name[Foo]) 
defined class Foo 

scala> lazy val x: Foo = Foo(Need(y)); lazy val y: Foo = Foo(Need(x)) 
x: Foo = <lazy> 
y: Foo = <lazy> 

scala> x.next.flatMap(_.next).value eq x 
res61: Boolean = true 
+0

Supongo que es discutible si esto es limpiador. Pero el desorden está en un lugar diferente, por lo que es una alternativa útil de cualquier manera. – Owen

+0

@Owen, ese es el enfoque al que he recurrido en el pasado. También me gustaría tener un soporte de idiomas de primera clase. – missingfaktor

Cuestiones relacionadas