- About Scala
- Documentation
- Code Examples
- Software
- Scala Developers
"Lazy" and the spec
Thu, 2010-05-27, 23:06
I understand why the compiler complains here:
scala> def f(n: Int) = { val fac: Int => Int = n => if(n == 0) 1 else n * fac(n - 1); fac(n) }
:6: error: forward reference extends over definition of value fac
def f(n: Int) = { val fac: Int => Int = n => if(n == 0) 1 else n * fac(n - 1); fac(n) }
^
It's because of this language at the beginning of chapter 4 in the spec:
"There is a restriction on forward references in blocks: In a statement
sequence s1 . . . sn making up a block, if a simple name in si refers to
an entity defined by sj where j >= i, then none of the definitions
between and including si and sj may be a value or variable definition."
However, I can make the error go away by adding "lazy":
scala> def f(n: Int) = { lazy val fac: Int => Int = n => if(n == 0) 1 else n * fac(n - 1); fac(n) }
f: (n: Int)Int
scala> f(5)
res0: Int = 120
And that's a good thing, of course! But what language in the spec
justifies it? Section 5.2 says how "lazy" behaves at runtime, but it
doesn't say anything about there being an exception to the chapter 4
rule at compile time. After all, "lazy val" is still technically a
value definition.
Is this a hole in the spec?
--
Seth Tisue @ Northwestern University | http://tisue.net
lead developer, NetLogo: http://ccl.northwestern.edu/netlogo/
On Thursday, May 27, 2010 06:04:27 pm Seth Tisue wrote:
> I understand why the compiler complains here:
>
> scala> def f(n: Int) = { val fac: Int => Int = n => if(n == 0) 1 else n *
> fac(n - 1); fac(n) } :6: error: forward reference extends over
> definition of value fac def f(n: Int) = { val fac: Int => Int = n => if(n
> == 0) 1 else n * fac(n - 1); fac(n) } ^
>
> It's because of this language at the beginning of chapter 4 in the spec:
>
> "There is a restriction on forward references in blocks: In a statement
> sequence s1 . . . sn making up a block, if a simple name in si refers to
> an entity defined by sj where j >= i, then none of the definitions
> between and including si and sj may be a value or variable definition."
>
> However, I can make the error go away by adding "lazy":
>
> scala> def f(n: Int) = { lazy val fac: Int => Int = n => if(n == 0) 1 else
> n * fac(n - 1); fac(n) } f: (n: Int)Int
>
> scala> f(5)
> res0: Int = 120
>
> And that's a good thing, of course! But what language in the spec
> justifies it? Section 5.2 says how "lazy" behaves at runtime, but it
> doesn't say anything about there being an exception to the chapter 4
> rule at compile time. After all, "lazy val" is still technically a
> value definition.
>
> Is this a hole in the spec?
It seems likely. The lazy parts of the spec were added after the forward
reference section. I submitted a patch:
http://lampsvn.epfl.ch/trac/scala/ticket/3468
and a bug:
http://lampsvn.epfl.ch/trac/scala/ticket/3503
-Mark