Понимание Scala -> синтаксис

Я получаю представление о Scala с помощью книги artima "Programming in 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")

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

С Уважением.


person oparisy    schedule 25.06.2013    source источник
comment
На самом деле они эквивалентны: (2->two) аналогично ((2, two)) и Map(1 -> "one") + ((2, "two")) прекрасно работает. Map(1 -> "one") + 2 -> "two" не будет работать с той же ошибкой, что и Map(1->"one") + (2, "two")   -  person om-nom-nom    schedule 26.06.2013
comment
Не могли бы вы переформулировать это как ответ, чтобы я мог его принять? :)   -  person oparisy    schedule 26.06.2013
comment
вы можете принять ответ Рекса, хотя было бы неплохо упомянуть, почему map + 2 -> "two" не работает (к сожалению, я не знаю).   -  person om-nom-nom    schedule 26.06.2013
comment
@om-nom-nom - Ну, это я знаю.   -  person Rex Kerr    schedule 26.06.2013
comment
@om-nom-nom map + 2 -> "two" даст вам (map + 2) -> "two": + и -> имеют одинаковый приоритет и левоассоциативны.   -  person gzm0    schedule 26.06.2013


Ответы (1)


Они точно такие же, благодаря этому классу в 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 вместо пары ключ-значение.

person Rex Kerr    schedule 25.06.2013
comment
Спасибо за объяснение, зачем нужны скобки, как предложил @om-nom-nom. - person oparisy; 26.06.2013