2013-06-25 7 views
2

Я получаю вкус Скалы через artima «Programming in Scala».Понимание Scala -> синтаксис

При представлении признаков Map авторы переходят к некоторым длинам, чтобы описать синтаксис -> как метод, который может быть применен к любому типу для получения кортежа.

И действительно:

scala> (2->"two") 
res1: (Int, String) = (2,two) 

scala> (2,"two") 
res2: (Int, String) = (2,two) 

scala> (2->"two") == (2, "two") 
res3: Boolean = true 

Но это не равнозначно:

scala> Map(1->"one") + (2->"two") 
res4: scala.collection.immutable.Map[Int,String] = Map(1 -> one, 2 -> two) 

scala> Map(1->"one") + (2, "two") 
<console>:8: error: type mismatch; 
found : Int(2) 
required: (Int, ?) 
      Map(1->"one") + (2, "two") 

Почему это так, так как мои первые тесты, кажется, показывают, что оба «пара» Синтаксисы построить кортеж?

С уважением.

+3

Фактически они эквивалентны: (2 -> «two») является аналогом ((2, «два»)) и «Карта (1 ->« один ») + ((2,« два »)) 'работает отлично. 'Map (1 ->« one ») + 2 ->« two »' не работает с той же ошибкой, что и «Карта (1 ->« один ») + (2,« два »)' –

+0

Не могли бы вы повторить это как ответ, чтобы я мог его принять? :) – oparisy

+0

вы можете принять ответ Rex, хотя будет полезно указать, почему «карта + 2 ->« два »' не работает (к сожалению, я не знаю). –

ответ

6

Они точно так же, благодаря этому классу в Predef (только частично воспроизведенных здесь):

final class ArrowAssoc[A](val __leftOfArrow: A) extends AnyVal { 
    @inline def -> [B](y: B): Tuple2[A, B] = Tuple2(__leftOfArrow, y) 
} 
@inline implicit def any2ArrowAssoc[A](x: A): ArrowAssoc[A] = new ArrowAssoc(x) 

Так что теперь вопрос в том, когда будет (a,b) синтаксис неоднозначным где (a -> b) нет? И ответ на вызовы функций, особенно, когда они перегружены:

def f[A](a: A) = a.toString 
def f[A,B](a: A, b: B) = a.hashCode + b.hashCode 
f(1,2)  // Int = 3 
f(1 -> 2) // String = (1,2) 
f((1, 2)) // String = (1,2) 

Карта + в частности запутается, потому что он перегружен версии нескольких аргументов, так что вы могли бы

Map(1 -> 2) + (3 -> 4, 4 -> 5, 5 -> 6) 

и таким образом интерпретирует

Map(1 -> 2) + (3, 4) 

как пытаются добавить как 3 к карте, а затем 4 на карте. Это, конечно, не имеет смысла, но не пытается интерпретировать другую интерпретацию.

С -> нет такой двусмысленности.

Однако, вы не можете

Map(1 -> 2) + 3 -> 4 

потому + и - имеют одинаковый приоритет. Таким образом, он интерпретируется как

(Map(1 -> 2) + 3) -> 4 

который снова терпит неудачу, потому что вы пытаетесь добавить 3 вместо пары ключ-значение.

+0

Спасибо, что объяснили, почему нужны парнеры, как это предлагает @ om-nom-nom. – oparisy