tags:

views:

186

answers:

3
val (xa, xb) = xs partition ( a > )

What is a > in above code and how is it different from a > _? (assume a is some predefined value)

A: 

I think it is actually exactly the same.

Jens Schauder
+1  A: 

It is not different at all, it's just a shorter version.

scala> val a = 10
a: Int = 10

scala> val xs = List(1, 2, 3, 4, 5, 11, 12, 13, 14, 15)
xs: List[Int] = List(1, 2, 3, 4, 5, 11, 12, 13, 14, 15)

scala> val (xa, xb) = xs partition ( a > )
xa: List[Int] = List(1, 2, 3, 4, 5)
xb: List[Int] = List(11, 12, 13, 14, 15)
Randall Schulz
+11  A: 

Any method that expects a function with some argument can be instead passed a one-argument method and, if the types work out, the method will be automatically converted.

So these all are valid:

class C { def go(i: Int) = -i }
val c = new C
List(1,2,3).foreach( println )
List(1,2,3).map( c go )

So, either a has the method > defined, or it can be implicitly converted to something with a > method. For example, this works:

List(1,2,3).partition(2 >)

because (EDIT: one would think this would be true....) there is an implicit conversion from Int to RichInt (the same one that gives you .toFloat and such), and RichInt has a > method defined. partition expects a function that takes Int and returns Boolean and 2 > is a method that takes Int and returns Boolean. So the conversion happens automatically.

(EDIT: but as @Lukas Rytz points out, it's even more tricky than that, because the compiler realizes that it can treat primitive ints specially, so even though > is not really a method on the object 2, because 2 is not an object, and primitives do not have methods, the compiler recognizes that deferring to RichInt would be slower. So, in fact, it just writes a method with the correct bytecode.)

Only if the correct conversion does not happen automatically (because of ambiguity, for example, or because you want to assign it to a variable) do you need to use _ to create a function out of a method. (And then it is not always exactly clear whether you are using _ to convert from method to function, or using _ as a placeholder for the input; fortunately, the result is the same either way.)

Rex Kerr
That's not entirely correct, there is no implicit conversion. The `Int` class has a `>` member (and also a `toFloat` in fact). The example after typing is `immutable.this.List.apply[Int](1, 2, 3).partition({ ((x$1: Int) => 2.>(x$1)) });`.
Lukas Rytz
@Lukas - Indeed--there goes compiler magic tricking me again. Because, of course, `Int` isn't a real class.
Rex Kerr
@Rex - For the scala compiler, `Int` is a real class with real methods (e.g. `>`), the special case is that the backend generates bytecode to use primitive operations instead of generating a method call. The fact that there are no source files for value classes is historical, and recently there was an attempt to change this, see http://github.com/soundrabbit/scala/commit/c13c67dda7c96c290d76a9b8763e559493704b9d. This might eventually make it into trunk.
Lukas Rytz
@Lukas - I didn't mean that the Scala compiler didn't internally use a class to keep track of what was going on with Int, just that to the coder and to the bytecode `2` is not a class. Try doing `2.getClass`, for example. The list of problems on the attempt to change to using source code also highlights how specially primitives are treated.
Rex Kerr
@Rex, that's right, value types are not class types. Thanks for clearing this up.
Lukas Rytz