Skip to content

Instantly share code, notes, and snippets.

@milessabin
Created February 17, 2013 21:59
Show Gist options
  • Save milessabin/4973733 to your computer and use it in GitHub Desktop.
Save milessabin/4973733 to your computer and use it in GitHub Desktop.
Lazy pattern matching in Scala.
Welcome to Scala version 2.10.0 (Java HotSpot(TM) 64-Bit Server VM, Java 1.7.0_05).
Type in expressions to have them evaluated.
Type :help for more information.
scala> def foo = { println("foo"); "foo" }
foo: String
scala> def bar = { println("bar"); "bar" }
bar: String
scala> def baz = { println("baz"); "baz" }
baz: String
scala> lazy val List(a, b, c) = List(foo, bar, baz)
a: String = <lazy>
b: String = <lazy>
c: String = <lazy>
scala> a
foo
bar
baz
res0: String = foo
scala> b
res1: String = bar
scala> c
res2: String = baz
@mergeconflict
Copy link

The reason all three values are forced isn't because lists are strict, it's because tuples are. When you declare:

lazy val List(a, b, c) = List(foo, bar, baz)

The compiler translates it to something like:

lazy val anon$ = List(foo, bar, baz) match { case List(a, b, c) => (a, b, c) }
lazy val a = anon$._1
lazy val b = anon$._2
lazy val c = anon$._3

When a is forced, it forces anon$ which is a tuple (constructed on the right hand side of the synthetic case clause). Tuple fields are strict. This sort of feels like a language spec bug to me... It seems like you want the compiler to synthesize some sort of LazyTuple in cases like this instead.

@mergeconflict
Copy link

By the way, just to prove the issue isn't list strictness:

scala> lazy val Stream(a,b,c) = Stream.iterate(0, 3) { x => println("oh noes"); x + 1 }
a: Int = <lazy>
b: Int = <lazy>
c: Int = <lazy>

scala> a
oh noes
oh noes
res0: Int = 0

@mergeconflict
Copy link

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment