Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Confused about Scala method calling conventions, specifically the sum function on Seq

I was playing around with the new Scala IDE (Eclipse 3.6.2 + Scala IDE 2.0.0 [Scala 2.9.0]) and I tried to do something simple like this:

(1 to 10).sum

That works fine, but I've been doing a lot of Groovy also recently and I automatically wrote:

(1 to 10).sum()

This second version gives me a compiler error in the IDE with the following message:

not enough arguments for method sum: (implicit num: Numeric[B])B. Unspecified value parameter num.

I see on the Scala API that there are two versions of sum, one that takes no parameters and one that takes the implicit above. Do I have to call zero-argument methods without parentheses?

like image 952
Phuong LeCong Avatar asked Apr 04 '11 22:04

Phuong LeCong


2 Answers

The answer is that if you specify a parameter list (i.e. use the parens), then you must specify the parameters in it (or, more accurately, those without defaults).

If you omit the parens on a non-empty parameter list whose parameters are implicit, then the compiler can inject them for you (assuming it can find the relevant implicits unabmiguously in your scope: as in your first example)

1 to 10 sum

If you want to pass in the parameter yourself (there is no need to do so in this example), then you can take advantage of Predef.implicitly which basically returns the unabiguous in-scope implicit value (assuming there is one). Their use here would be:

(1 to 10).sum(implicitly[Numeric[Int]])
(1 to 10).sum[Int](implicitly)

This is particularly important in methods which take more than one implicit parameter, of which you might only wish to override one (you can then use implicitly for the others). For example, in scalaz

aFoldable.sum(implicitly, myMonoid) //uses implicit Foldable but bespoke monoid

For your question about the scaladoc use case; this is a phantom entry to show you how to use the (otherwise potentially confusing) method with the implicit parameter list. The existence of this scaladoc entry can be traced to this notorious question.

like image 127
oxbow_lakes Avatar answered Oct 19 '22 07:10

oxbow_lakes


There is only one version. If you carefully look at the API, the entry that has no parentheses says "[use case]" in the beginning. This is a synthetic duplicate entry in the API docs which is for easier grasping; the use-case entries are basically reduced full entries for some common scenarios. More on this in this question: Scaladoc [use case]

The reason why the second call (...sum()) fails is that although the argument is implicit, it doesn't have a default value. You can only omit arguments inside parentheses when default values are provided. Although this sounds illogical, implicit arguments are treated differently: either you supply them explicitly, then you need to use the parentheses, or you omit them (because an implicit is found in scope), but then you also need to drop the parentheses. This is to facilitate better readability, e.g.

def test(fun: Int => Int)(implicit s: String)

now you can write test { i => i } and not test(i => i)() which is awkward.

like image 3
0__ Avatar answered Oct 19 '22 09:10

0__