Подчеркивание в именованных аргументах

Может кто-нибудь объяснить мне, что именно здесь происходит? Я не полностью вдаюсь в это прямо сейчас:

val s = Seq(1D,2D,3D,4D)
case class WithUnit(value: Double, unit: String)
s map { WithUnit(_,"cm") } // works
s map { WithUnit(value = _ , unit = "cm") } // error: missing parameter type for expanded function ((x$2) => value = x$2)

Я думаю, что компилятор не может вывести тип параметра, потому что я написал имя аргумента. Но почему нет? Это не должно быть сложнее только из-за указания имени аргумента?!

Спасибо!

Ответ 1

Когда вы написали:

 WithUnit(value = _, unit = "cm")

Вы хотели, чтобы это означало:

 x => WithUnit(value = x, unit = "cm")

Но если вы внимательно посмотрите на сообщение об ошибке, вы увидите, что компилятор не видел этого, он проанализировал его как:

 WithUnit(x => value = x, unit = "cm"})

Как вы можете видеть, объект _ больше привязан, чем вы хотели.

_ всегда выбирает самый жесткий невырожденный объем, который он может. Объем определяется чисто синтаксически, во время разбора, независимо от типов.

Невырожденным я имею в виду, что компилятор не думал, что вы имели в виду:

WithUnit(value = x => x, unit = "cm")

Самый строгий невырожденный объем означает область, определяемую самой внутренней функциональной скобкой относительно подчеркивания. Без такого правила компилятор не смог бы знать, что _ соответствует какой функции, когда вызовы функций вложены.

Ответ 2

Попробуйте следующее:

scala> val withUnits = s map { x => WithUnit(value = x, unit = "cm") }
withUnits: Seq[WithUnit] = List(WithUnit(1.0,cm), WithUnit(2.0,cm), WithUnit(3.0,cm), WithUnit(4.0,cm))

Проблема заключается в использовании подчеркивания для прямого определения любой функции.

Подробное описание находится в главе 8.5. Синтаксис заполнителя в книге "Программирование в Scala" .