0

As https://www.scala-lang.org/api/current/scala/collection/immutable/List.html#sortWith(lt:(A,A)=%3EBoolean) :

List("Steve", "Tom", "John", "Bob").sortWith(_.compareTo(_) < 0) = List("Bob", "John", "Steve", "Tom")

the param of sortWith is:

lt: (A, A) => Boolean

where a function with two params and return a boolean

but compareTo have only one param:

def compareTo(that: A): Int

if compareTo is a function,it have two params.but it's scala,so compareTo is a method,it's have only one param

so why there can use compareTo in sortWith?It seems not accord with the type signature of sortWith

Mario Galic
  • 47,285
  • 6
  • 56
  • 98
wang kai
  • 1,673
  • 3
  • 12
  • 21
  • 3
    Notice the function passed to `sortWith` is not `compareTo`, but the lambda `_.compareTo(_) < 0`. – Bergi May 12 '21 at 00:59
  • 5
    On what are you calling `compareTo`? On a magic object created out of no where? No, you are calling it in the object passed as the first argument of the function. If we remove the sugar syntax of the `_` syntax it should be clear: `_.compareTo(_)` is equivalent to `(a1, a2) => a1.compareTo(a2)` so you can clearly see you have a two arguments function :) – Luis Miguel Mejía Suárez May 12 '21 at 01:03
  • @LuisMiguelMejíaSuárez I believe your comment should be posted as an answer ;) – Gaël J May 12 '21 at 12:46

1 Answers1

3

This usage of underscore is known as Placeholder Syntax for Anonymous Functions:

Such an expression represents an anonymous function where subsequent occurrences of underscores denote successive parameters.

Note each underscore refers to different parameter so for example

_ + _

expands to

(x1, x2) => x1 + x2

Also expression _ + _ makes use of point-free syntax as opposed to

_.+(_)

for example

List("Steve", "Tom", "John", "Bob").reduce((x1: String, x2: String) => x1.+(x2)) // : String = "SteveTomJohnBob"
List("Steve", "Tom", "John", "Bob").reduce((x1, x2) => x1.+(x2)) // : String = "SteveTomJohnBob"
List("Steve", "Tom", "John", "Bob").reduce(_.+(_)) // : String = "SteveTomJohnBob"
List("Steve", "Tom", "John", "Bob").reduce(_ + _) // : String = "SteveTomJohnBob"

so now it should be clearer why expression _.compareTo(_) < 0 works

List("Steve", "Tom", "John", "Bob").sortWith(_.compareTo(_) < 0) // : List[String] = List("Bob", "John", "Steve", "Tom")
List("Steve", "Tom", "John", "Bob").sortWith((x1, x2) => x1.compareTo(x2) < 0) // : List[String] = List("Bob", "John", "Steve", "Tom")

Another way to see this let's type-ascribe the sugared expression

scala> (_.compareTo(_) < 0): ((String, String) => Boolean)
val res0: (String, String) => Boolean = $Lambda$7865/418832725@18987bf5
Mario Galic
  • 47,285
  • 6
  • 56
  • 98