Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Differences in "prose" and "dot notation" when invoking a method with (explicit) implicit parameters

I'm not a Scala expert, and I'm confused about the syntax of calling a method with an implicit parameter.

Here's my situation:

I have a Spark RDD like this:

val myData: RDD[Array[String]] = ...

and have defined an Ordering for it:

object MyOrdering extends Ordering[Array[String]] = ...

I want to filter this RDD and take the top n entries in the RDD according to my Ordering. A Spark RDD has a method for taking the top n entries with this signature:

def top(num: Int)(implicit ord: Ordering[T]): Array[T] 

Initially I tried this code

myData filter { D =>
  D(9) == "yes"
} top(50)(MyOrdering)

Which fails with this error:

error: Int(50) does not take parameters
    } top(50)(MyOrdering)

However, this code works:

myData.filter(D => D(9) == "yes").top(50)(MyOrdering)

To my beginner's eye, the failing code sample and the working code sample look to be specifying equivalent logic. Am I wrong here? Am I actually doing something different in the two code samples? Or is this an issue with how the Scala compiler parses the code?

like image 507
Steve Hastings Avatar asked Nov 10 '22 19:11

Steve Hastings


1 Answers

You can only replace the dot . with a space for method invocation when the method is arity-1 (1 parameter list) or arity-0 (no parameter lists). For example, this fails to compile:

class Foo {
    def baz(x: Int)(y: Int) = this
    def qux(x: Int) = this
}

(new Foo) baz(1)(1) //Does not compile
(new Foo).baz(1)(1) //Allowed
(new Foo) qux(1) //Allowed, since qux is arity-1
(new Foo).qux(1) //Also allowed, of course

When the the last parameter list is implicit the compiler can treat a method with n parameter lists as if it has arity n-1 if the method is being invoked with an implicit argument:

class Foo {
    def baz(x: Int)(implicit y: Int) = this
}

implicit val y: Int = 1
(new Foo) baz(1) //Allowed
(new Foo).baz(1) //Also fine
(new Foo) baz(1)(2) //Still not allowed
(new Foo).baz(1)(2) //Still allowed

Read more about the rules for method invocation in the style guide.

like image 112
Ben Reich Avatar answered Nov 14 '22 22:11

Ben Reich