2012-02-24 1 views
6

Próbując odpowiedzieć na to pytanie: Leave off underscore in function literal Próbowałem zakodować przykład i stanąłem twarzą w twarz z dziwnym zachowaniem.Scala: odwrotny wynik podczas ucieczki podkreślenie z :::

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) 

Chociaż mam dobrej odpowiedzi, gdy używam _ lub x=> f(x) składnie.

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) 

Czy istnieje racjonalne wyjaśnienie, dlaczego myList przychodzi po 3::Nil w funkcji concat?

Odpowiedz

7

myList ::: _ oznacza: _.:::(myList), natomiast myList ::: oznacza myList.:::(_).

tl; dr

This post przechodzi w bardziej szczegółowo o prawo metod asocjacyjnych. Co się tutaj dzieje jest:

  • def concat0:(List[Int]=> List[Int]) = x=> myList:::x
    • Scala kompilator może wnioskować, że X czy typu List[Int]
    • List ma metodę :::
    • z powodu przepisów prawa skojarzeń, to zamienia się x.:::(myList) , który przedkłada myList do x.
  • def concat (List [Int] => List [Int]) = myList :::
    • myList jeśli typu List[Int]
    • Nie ma prawa strona :::, więc nie brak skojarzenia z prawdą
    • Zamiast tego kompilator podaje a. pomiędzy myList i :::
    • myList.::: jest taka sama jak x => myList.:::(x), który wstawia x do myList.
+0

Dzięki za naprawdę szczegółowy i przejrzysty post. –