2012-02-04 32 views
9

Điều gầnTrong Scala hiện nay, là có một cách sạch hơn để làm "mẫu constructor lười biếng"

case class Foo(lazy next: Foo) 

mà tôi đã có thể đưa ra được

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

tôi thấy một vấn đề được liệt kê add lazy parameters vì vậy tôi đoán nó sẽ được thêm vào một ngày nào đó. Trong khi chờ đợi, có ai biết một thủ thuật sạch hơn so với ở trên không?

+0

Điều đáng nói là phương thức 'unapply' không lười, vì vậy việc cố khớp mẫu' Foo' thành một 'Foo' khác sẽ dẫn đến' tiếp theo' được đánh giá mà bạn không muốn. –

+0

@BrianMcCutchon Đó là một điểm tốt. Tôi cho rằng cách duy nhất để làm cho nó lười biếng là thêm indirection, như trong 'def unapply (foo: Foo) = Some (() => foo.next)'? – Owen

+0

Điều đó dường như hoạt động. Tôi chỉ tránh sử dụng 'unapply' cho các lớp học lười biếng của mình. Trong trường hợp đó, mặc dù, bạn cần gọi một cách rõ ràng hàm, như 'trường hợp Foo (n) => Foo (doSomething (n()))'. Tại thời điểm đó, có thể tốt hơn nếu sử dụng 'Need'. (Ngoài ra, nếu bạn đi đường 'Need', bạn có thể định nghĩa một hàm tạo quá tải cho' Foo' lấy tham số gọi theo tên và biến nó thành 'Need'.) –

Trả lời

6

Có thể scalaz.Need? Điều này đã được đề xuất cho tôi trong 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

Tôi cho rằng nó có thể gây tranh cãi cho dù đây là sạch hơn. Nhưng sự lộn xộn là ở một nơi khác, vì vậy nó là một cách thay thế hữu ích một trong hai cách. – Owen

+0

@Owen, đó là cách tiếp cận mà tôi đã sử dụng trong quá khứ. Tôi cũng muốn được hỗ trợ ngôn ngữ hạng nhất. – missingfaktor

Các vấn đề liên quan