избыточная информация о типе параметра в частично примененном определении функции - PullRequest
5 голосов
/ 18 декабря 2011
def foo(num:Int, str:String):Int = 1

val bar = foo(3, _)  // compiler complains "missing parameter type for expanded function ((x$1) => test(3, x$1))"

val baz = foo(3, _:String) // compiles fine

Почему я должен явно указывать тип _, когда он выглядит выведенным из контекста?

РЕДАКТИРОВАТЬ : переименован во избежание конфликта имен по предложению Дэвида Зоргеля.

Ответы [ 2 ]

3 голосов
/ 18 декабря 2011

Я думаю, что объяснение Дэвида Зоргеля, по сути, правильное: если тип T имеет неявное преобразование в строку, тогда val bar = foo(3, _:T) допустимо, давая функцию типа T => Int, которая не связана с String => Int.

Почему компилятор не делает разумного предположения (при отсутствии явной типизации), что тип на самом деле такой же, как в методе (что является сутью вашего вопроса), я не знаю - ямогу только догадываться, потому что это усложнит спецификацию языка.

Там, где типы не указаны, т.е. val bar = foo(_, _), кажется, что компилятор интерпретирует это как простое eta-преобразование, такое же, как val bar = foo _, что делает* String => Int.

Моя предпочтительная форма - указывать тип функции слева, что позволяет вам легко видеть тип bar:

* 1016.*

Если у вас аллергия на повторный набор слова String, вы можете написать

val bar = (foo _).curried(3)
3 голосов
/ 18 декабря 2011

Прежде всего, чтобы избежать путаницы между «def test» и «val test», давайте напишем:

def foo(num:Int, str:String):Int = 1

val bar = foo(3, _)  // compiler complains "missing parameter type for expanded function ((x$1) => foo(3, x$1))"

val baz = foo(3, _:String) // compiles fine

Что следует из контекста, так это только то, что аргумент bar должен каким-то образом быть преобразован в строку. Это может быть связано с наследованием (если вместо String вы используете неконечный тип) или из-за неявного преобразования.

По существу, потенциал для имплицитов означает, что аргумент для bar может быть практически любого типа, поэтому код, который написан, действительно не указан. Я не знаю, действительно ли компилятор проверяет, есть ли какие-либо соответствующие неявные преобразования в области видимости, прежде чем выдавать ошибку «пропущенного типа», но я бы не догадался. (В случае с String, скорее всего, будет куча). Было бы хрупко и непонятно, если бы сигнатура baz изменилась в результате импорта нового неявного, который мог бы создать строку.

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