Почему ((_: Int, _: Int) => _ / _) не компилируется, а ((_: Int) / (_: Int)) делает?
Я изучаю Scala, и у меня очень простой вопрос. Рассмотрим следующие два выражения с использованием синтаксиса заполнителя -
// Syntax A
val fnA = (_: Int, _: Int) => _ / _
// Syntax B
val fnB = (_: Int) / (_: Int)
и их попытки применения -
// Syntax A
fnA(33, 3)
// Syntax B
fnB(33, 3)
Из этих двух только B и App(B) являются допустимым синтаксисом, и я не уверен, почему. Если компилятор может вывести аргументы (и порядок их применения) вfnB
почему он не может сделать это для fnA
? Я основываю свой вопрос на том, чтоfnB
это сокращение для fnA
и я почти уверен, что в этом рассуждении есть изъян. Я просто не уверен, в чем заключается недостаток.
1 ответ
Значение подчеркиваний слева от стрелки =>
(_: Int, _: Int) => ...
имеют разные от значения подчеркивания вокруг оператора инфиксного/
(_: Int) / (_: Int)
Первые означают что-то вроде
"Мы определяем функцию, которая принимает два аргумента, однако мы не будем использовать эти аргументы в теле функции"
в то время как последнее является сокращением для определения функции двух аргументов
(x: Int, y: Int) => x / y
Например,
(_: Int, _: Int) => (_: Int) / (_: Int)
десахаров к чему-то вроде
(a: Int, b: Int) => ((x: Int, y: Int) => x / y)
где мы видим аргументы a
а также b
не используются в теле, что является еще одной функцией ((x: Int, y: Int) => x / y)
.
Даниил документирует два значения как
_ + _ // Anonymous function placeholder parameter
_ => 5 // Discarded parameter
В качестве примечания рассмотрим несколько аналогичную ситуацию на уровне типов, включающую конструкторы типов и их границы, где значение подчеркивания зависит от контекста.
CC[_] <: Iterable[_]
Лично я обманываю меня, думая, что это эквивалентно
CC[x] <: Iterable[x]
однако это не так, и значение подчеркивания слева от <:
это отличается от значения по праву
CC[x] <: Iterable[y] forSome {type y}
Обратите внимание, как x
не появляется в Iterable[y] forSome {type y}
. Адриан документирует это в разделе " Общие ловушки":
... возможно, удивительно,
CC[_] <: Traversable[_]
не эквивалентноCC[X] <: Traversable[X]
. Первый расширяется доCC[X] <: Traversable[T] forSome {type T}
, гдеT
экзистенциально связана и, следовательно, не связана сX
.
и в комментарии к типу границ конструктора типа
сравнивая уровень типов и значений, очень жаль, что подчеркивание уровня типа ведет себя иначе, чем подчеркивание уровня значения. На ценностном уровне
_ + _
действительно означает(x, y) => x + y
, функция. Как указано в моем другом комментарии, подчеркивание на уровне типа является контекстно-зависимым и никогда не вводит функцию уровня типа. Это либо определение параметра анонимного типа, либо анонимный экзистенциальный. Ни у одного из них нет эквивалентов на уровне стоимости.
Следовательно, мы должны быть осторожны при интерпретации значения подчеркивания в его контексте.