Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Scala by name parameters with multiple argument lists and currying

Tags:

scala

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?

like image 523
Luke Studley Avatar asked Nov 06 '12 07:11

Luke Studley


2 Answers

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
like image 69
Régis Jean-Gilles Avatar answered Oct 28 '22 03:10

Régis Jean-Gilles


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.

like image 39
som-snytt Avatar answered Oct 28 '22 03:10

som-snytt