Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Lazier val definitions with pattern matching #7141

Closed
scabug opened this issue Feb 18, 2013 · 2 comments
Closed

Lazier val definitions with pattern matching #7141

scabug opened this issue Feb 18, 2013 · 2 comments

Comments

@scabug
Copy link

scabug commented Feb 18, 2013

Miles Sabin stumbled upon an interesting corner case in how lazy val definitions interact with pattern matching. The basic idea:

scala> val stream = Stream.iterate(0, 3) { x => println(x); x + 1 }
stream: scala.collection.immutable.Stream[Int] = Stream(0, ?)

scala> lazy val Stream(a, b, c) = stream
a: Int = <lazy>
b: Int = <lazy>
c: Int = <lazy>

scala> a
0
1
res0: Int = 0

One would hope that only a is forced, but all three values are. This is because of how the val definition is expanded:

lazy val $fresh = stream match {
  case Stream(a, b, c) => (a, b, c)
}
lazy val a = $fresh._1
lazy val b = $fresh._2
lazy val c = $fresh._3

The culprit is construction of a tuple in the synthesized case clause: tuples are strict, so forcing a forces the whole tuple.

If the language spec instead required an expansion similar to:

lazy val a = stream match { case Stream(a, _, _) => a }
lazy val b = stream match { case Stream(_, b, _) => b }
lazy val c = stream match { case Stream(_, _, c) => c }

Or if the library had LazyTuple types:

lazy val $fresh = stream match {
  case Stream(a, b, c) => LazyTuple3(a, b, c)
}
lazy val a = $fresh._1
lazy val b = $fresh._2
lazy val c = $fresh._3

... then the laziness would be appropriately deferred to Stream.

That being said, I don't actually know how one would write an appropriate Stream.unapplySeq, or unapply for any data type in general, that doesn't force all value members. Seems like a separate unapplyLazy, returning an Option[LazyTuple], would be necessary... and that's horrible.

@scabug
Copy link
Author

scabug commented Feb 18, 2013

Imported From: https://issues.scala-lang.org/browse/SI-7141?orig=1
Reporter: Dan Rosen (mergeconflict)

@SethTisue
Copy link
Member

interesting, but more of a language design discussion, and surely out of scope for Scala 2 anyway

@SethTisue SethTisue closed this as not planned Won't fix, can't repro, duplicate, stale Mar 31, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants