Allow by-name repeated parameters
See original GitHub issueMotivation
Scala so far does not allow by-name repeated parameters. But I can’t see a good reason why this combination should be disallowed. Also, the combination is necessary to allow vararg parameters that are passed as expressions to inline methods (instead of being lifted out).
Syntax
The syntax for ParamType
becomes
ParamType ::= [`=>'] ParamValueType
ParamValueType ::= Type [`*']
The syntax implies that a type such as => T*
, which is both by-name and repeated is interpreted as => (T*)
, that is, as a by-name type of a repeated type.
Translation Rules
If a parameter has a by-name repeated type => T*
it matches an arbitrary number of actual arguments of type T
. As usual for by-name parameters, the arguments are not evaluated at the point of call. Instead, all arguments are evaluated each time the parameter is referenced in the called method.
The same holds for an vararg argument of the form e: _*
. The argument expression e
is evaluated each time the parameter is referenced in the called method.
Issue Analytics
- State:
- Created 8 years ago
- Comments:11 (7 by maintainers)
Top GitHub Comments
It’s more general sure, but as Runar says, liberties constrain and constraints liberate. Or as the Talmud says, whoever increases, decreases. Specifically, as Martin has said, by taking the more general interpretation the implementation is forced to be much less performant. Also (he said) it would a much more complicated implementation. How would you implement such a thing? In fact how would it even work? Given def m(xs: =>Int*) { // what is the type of xs? val ys = xs.to[X] // where X is List, Seq, whatever. What is the element type? val z = xs.head // what does this desugar to? xs.filter(somePredicate).foreach(println) // what are the semantics? } I guess you could either (1) make xs have some special collection type, e.g. LazyList, or (2) make it be some sort of Seq[=>Int], with new rules.
On second thought, if we had an actual LazyList as has been discussed (unlike Stream where the head is not truly lazy), one could suggest that
T*
becomes a Seq while=>T*
becomes a LazyList. But actually, by-name is different than lazy: lazy means evaluated 0 or 1 times, but by-name means evaluated 0 or more times. So you’d need a new collection (ByNameSeq) which is like LazyList but much less useful.On a different note (OT), it would be interesting to be able to declare parameters to be like lazy rather than regular call-by-name.
On Fri, Aug 19, 2016 at 12:28 PM Sean Vieira notifications@github.com wrote:
Seems to work (in 2.11.6): http://scastie.org/9184