Расширение обозначения Scala для пар

Scala, в Predef, определяет поддержку для -> и (здесь немного очищено):

final class ArrowAssoc[A](val __leftOfArrow: A) extends AnyVal {    
    def -> [B](y: B): Tuple2[A, B] = Tuple2(__leftOfArrow, y)
    def →[B](y: B): Tuple2[A, B] = ->(y)
}

Это удобно для создания пар с использованием нотации стрелки вместо синтаксиса простого кортежа:

scala> "foo" → 42
res0: (String, Int) = (foo,42)

Этот синтаксис стрелки можно легко расширить с помощью определения типа и экстрактора (здесь отображается только ):

type →[A, B] = (A, B)
object → { def unapply[A, B](t: (A, B)) = Some(t) }

Это позволяет писать такие вещи, как:

"a" → 42 match { case a → b ⇒ println(s"found `$a` and `$b`") }

и

def foo[A, B](t: A → B) = ???

Мне интересно, если какая-либо причина Scala не определяет их также в стандартной библиотеке. Есть ли недостатки этих определений?

Ответы

Ответ 1

Вот один недостаток. Возможность делать как

def foo[A, B](t: A -> B) = ???

и

def foo[A, B](t: A => B) = ???

будет путать. Если типы не выстраиваются в линию, компилятор наверняка поймает его. Однако только опытный программист Scala быстро понял сообщение об ошибке.

Ответ 2

Я уверен, что -> существует только для того, чтобы легко прочитать способ инициализации записей Map. Он не предназначен для общего назначения пары. Вы должны использовать синтаксис (a, b) для всех других целей, чтобы избежать путаницы. Как бы то ни было, существует два разных способа представления пары ((a, b) и Tuple2(a, b)). Нам не нужна третья.

Вы можете утверждать, что вам понадобится a → extractor для выполнения сопоставления шаблонов в записях Map, чтобы выяснить, какая часть является ключом, а какая является значением, но помните, что case (key, value) делает это различие столь же ясным, Это только в случае инициализации, что нет четкого способа отличить, какая часть является ключом и которая является значением, кроме использования ->.