Почему ((_: ​​Int, _: Int) => _ / _) не компилируется, когда ((_: ​​Int) / (_: Int)) выполняется? - PullRequest
2 голосов
/ 12 января 2020

Я учусь Scala и у меня очень простой c вопрос. Рассмотрим следующие два выражения с использованием синтаксиса заполнителя -

// 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) являются допустимым синтаксисом, а I не знаю почему. Если компилятор может вывести аргументы (и порядок их применения) в fnB, почему он не может сделать это для fnA? Я основываю свой вопрос на предпосылке, что fnB является сокращением для fnA, и я почти уверен, что в этом рассуждении есть изъян. Я просто не уверен, что это за недостаток.

1 Ответ

5 голосов
/ 12 января 2020

Значение подчеркивания слева от стрелки =>

(_: 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}. Адриан документирует это под Common Pitfalls :

... возможно, что удивительно, CC[_] <: Traversable[_] не эквивалентно CC[X] <: Traversable[X]. Первый расширяется до CC[X] <: Traversable[T] forSome {type T}, где T экзистенциально связан и, таким образом, не связан с X.

и в комментариях к для типов. Конструктор

, сравнивающий уровень типов и значений, весьма прискорбно, что подчеркивание на уровне типов ведет себя не так, как подчеркивание на уровне значений. На уровне значений _ + _ действительно означает (x, y) => x + y, функцию. Как уже упоминалось в моем другом комментарии, подчеркивание на уровне типа является контекстно-зависимым и никогда не вводит функцию уровня типа. Это либо определение параметра анонимного типа, либо анонимный экзистенциальный. Ни один из них не имеет эквивалентов на уровне значений.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...