2012-02-04 7 views
9

en yakın şey , ben ile gelip mümkün olmuştur "tembel yapıcı desenini"

case class Foo(lazy next: Foo) 

yapmak daha temiz bir yolu var buldum

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

olduğu add lazy parameters listelenen bir sorun, bu yüzden birgün eklenecektir. Bu arada, kimse yukarıdakilerden daha temiz bir şey biliyor mu?

+0

O kadar içine 'Foo' maç desen çalışırken, sizin' unapply' yöntem tembel olmadığını belirtmekte yarar var başka 'Foo'' next' istediğiniz olmayabilir, hangi değerlendirilmektedir sonuçlanacaktır. –

+0

@BrianMcCutchon Bu iyi bir nokta. Ben tembel yapmak için tek yolu, dolaylı olarak eklemek gibi olurdu, çünkü unapply (foo: Foo) = Some (() => foo.next) '? – Owen

+0

Bu işe yarıyor. Sadece tembel vaka sınıflarım için “unapply” kullanıyorum. Bu durumda, işlevini açıkça çağırmanız gerekir; örneğin, Foo (n) => Foo (doSomething (n())) 'gibi. Bu noktada, 'Need' kullanmak daha iyi olabilir. (Ayrıca, "İhtiyaç" rotasına giderseniz, "Foo" için bir isim-ismi parametresi alan ve bunu "İhtiyaç" haline getiren aşırı yüklü bir kurucu tanımlayabilirsiniz.) –

cevap

6

Belki scalaz.Need? Bu bana this answer numaralı telefondan önerildi.

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

Bunun olup olmadığını tartışabiliriz. temizleyici. Ancak dağınıklık farklı bir yerdedir, bu yüzden her iki durumda da yararlı bir alternatiftir. – Owen

+0

@Owen, geçmişte başvurduğum yaklaşım budur. Ben de birinci sınıf dil desteğine sahip olmak isterim. – missingfaktor