Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Scala: inverse result while escaping underscore with :::

When trying to answer this question : Leave off underscore in function literal I tried to code an example and I faced a strange behavior.

scala> val myList = 1::2::Nil
myList: List[Int] = List(1, 2)

scala> def concat:(List[Int]=> List[Int]) = myList:::
concat: (List[Int]) => List[Int]

scala> concat(3::Nil)
res1: List[Int] = List(3, 1, 2)

While I have the good answer when I use _or x=> f(x) syntaxes.

scala> def concat0:(List[Int]=> List[Int]) = x=> myList:::x
concat0: (List[Int]) => List[Int]

scala> def concat1:(List[Int]=> List[Int]) = myList::: _
concat1: (List[Int]) => List[Int]

scala> concat0(3::Nil)
res2: List[Int] = List(1, 2, 3)

scala> concat1(3::Nil)
res3: List[Int] = List(1, 2, 3)

Is there a rational explanation why myList comes after 3::Nilin the function concat?

like image 892
Christopher Chiche Avatar asked Feb 24 '12 18:02

Christopher Chiche


1 Answers

myList ::: _ translates to _.:::(myList), whereas myList ::: translates to myList.:::(_).

tl;dr

This post goes into more detail about right associative methods. What's happening here is:

  • def concat0:(List[Int]=> List[Int]) = x=> myList:::x
    • Scala compiler can infer that x if of type List[Int]
    • List has a ::: method
    • Because of the rules of right associativity, this turns into x.:::(myList), which prepends myList to x.
  • def concat:(List[Int]=> List[Int]) = myList:::
    • myList if of type List[Int]
    • There is no right hand side of :::, so there's no right-associativity
    • Instead, compiler infers a . between myList and :::
    • myList.::: is the same as x => myList.:::(x), which prepends x to myList.
like image 129
leedm777 Avatar answered Nov 10 '22 05:11

leedm777