Сопоставление с образцом принимает входные данные и декомпозирует их с помощью функции unapply
. Таким образом, в вашем случае unapply(4)
должен будет вернуть два числа, сумма которых равна 4. Однако есть много пар, сумма которых равна 4, поэтому функция не будет знать, что делать.
Вам нужно, чтобы 2
был как-то доступен для функции unapply
. Класс специального случая, в котором хранится 2
, подойдет для этого:
case class Sum(addto: Int) {
def unapply(i: Int) = Some(i - addto)
}
val Sum2 = Sum(2)
val Sum2(x) = 5 // x = 3
(Было бы неплохо иметь возможность сделать что-то вроде val Sum(2)(y) = 5
для компактности, но Scala не допускает параметризованные экстракторы; см. здесь .)
[РЕДАКТИРОВАТЬ: Это немного глупо, но вы могли бы также сделать следующее:
val `2 +` = Sum(2)
val `2 +`(y) = 5 // y = 3
]
РЕДАКТИРОВАТЬ: Причина, по которой работает head::tail
, заключается в том, что есть только один способ отрубить голову от хвоста списка.
Нет ничего особенного в ::
против +
: вы можете использовать +
, если у вас есть заранее определенное представление о том, как вы хотите, чтобы оно разбивало число. Например, если вы хотите, чтобы +
означало «разделить пополам», то вы можете сделать что-то вроде:
object + {
def unapply(i: Int) = Some(i-i/2, i/2)
}
и используйте его как:
scala> val a + b = 4
a: Int = 2
b: Int = 2
scala> val c + d = 5
c: Int = 3
d: Int = 2
EDIT: наконец, это объясняет, что при сопоставлении с шаблоном A op B
означает то же самое, что и op(A,B)
, что делает синтаксис красивым.