Почему ((_: ​​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, функция. Как указано в моем другом комментарии, подчеркивание на уровне типа является контекстно-зависимым и никогда не вводит функцию уровня типа. Это либо определение параметра анонимного типа, либо анонимный экзистенциальный. Ни у одного из них нет эквивалентов на уровне стоимости.

Следовательно, мы должны быть осторожны при интерпретации значения подчеркивания в его контексте.

Другие вопросы по тегам