In Scala (2.9.2) I am trying to create a function that provides some other value when accessed
() => Any
I thought I was successfully doing this via a by name / currying solution:
def byName(theValue : => Any)() : Any = theValue
val myHolder = byName(myValue)_
So my holder is of the correct type. However I find that in the course of creating this curried function the by name parameter is evaluated. If I do the following instead it works as intended:
def byName(theValue : => Any) : Any = () => theValue
val myHolder = byName(myValue)
I conclude some part of the currying process is referencing the first parameter list and triggering its evaluation. Can anybody confirm that and/or explain why or if there are any guidelines around using by name parameters with multiple parameter lists?
This seems like a bug to me. I could trigger this strange behaviour in scala 2.9.1, but not in scala 2.10 RC1 so I guess this was fixed at some point.
In scala 2.9.1:
Welcome to Scala version 2.9.1.final (Java HotSpot(TM) Client VM, Java 1.6.0_27).
Type in expressions to have them evaluated.
Type :help for more information.
scala> def byName(theValue : => Any)() : Any = theValue
byName: (theValue: => Any)()Any
scala> def myValue: String = { println("Computing myValue"); "hello" }
myValue: String
scala> val myHolder = byName(myValue)_
Computing myValue
myHolder: () => Any = <function0>
scala> myHolder()
res0: Any = hello
In scala 2.10-RC1:
Welcome to Scala version 2.10.0-RC1 (Java HotSpot(TM) Client VM, Java 1.6.0_27).
Type in expressions to have them evaluated.
Type :help for more information.
scala> def byName(theValue : => Any)() : Any = theValue
byName: (theValue: => Any)()Any
scala> def myValue: String = { println("Computing myValue"); "hello" }
myValue: String
scala> val myHolder = byName(myValue)_
myHolder: () => Any = <function0>
scala> myHolder()
Computing myValue
res0: Any = hello
The issues are https://issues.scala-lang.org/browse/SI-302 and https://issues.scala-lang.org/browse/SI-5610
Personally, I find what is now the "old" behavior more intuitive: Partial application means something is applied.
Or as Odersky had it:
No, that's how eta expansion is defined. You don't just wrap a lambda around the expression, you evaluate what you can first.
But conversely, it's easier to force evaluation than to devise a syntax for suspending it.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With