Запутался в соглашениях о вызовах методов Scala, особенно в функции суммы в Seq

Я играл с новой Scala IDE (Eclipse 3.6.2 + Scala IDE 2.0.0 [Scala 2.9.0]) и попытался сделать что-то простое:

(1 to 10).sum

Это прекрасно работает, но в последнее время я также много работал с Groovy и автоматически написал:

(1 to 10).sum()

Эта вторая версия дает мне ошибку компилятора в IDE со следующим сообщением:

недостаточно аргументов для суммы метода: (неявное число: Numeric[B])B. Номер параметра с неопределенным значением.

Я вижу в Scala API, что есть две версии sum, одна из которых не принимает параметров, а другая принимает неявное указанное выше. Должен ли я вызывать методы без аргументов без круглых скобок?


person Phuong LeCong    schedule 04.04.2011    source источник


Ответы (2)


Ответ заключается в том, что если вы указываете список параметров (т.е. используете круглые скобки), тогда вы должны указать параметры в нем (точнее, без значений по умолчанию).

Если вы опускаете скобки в непустом списке параметров, параметры которого равны implicit, то компилятор может внедрить их за вас (при условии, что он может однозначно найти соответствующие имплициты в вашей области: как в вашем первом примере)

1 to 10 sum

Если вы хотите передать параметр самостоятельно (в этом примере этого делать не нужно), вы можете воспользоваться Predef.implicitly, который в основном возвращает однозначное неявное значение в области видимости (при условии, что оно есть). Их использование здесь будет:

(1 to 10).sum(implicitly[Numeric[Int]])
(1 to 10).sum[Int](implicitly)

Это особенно важно в методах, которые принимают более одного неявного параметра, из которых вы можете переопределить только один (затем вы можете использовать implicitly для остальных). Например, в scalaz

aFoldable.sum(implicitly, myMonoid) //uses implicit Foldable but bespoke monoid

На ваш вопрос о scaladoc варианте использования; это фиктивная запись, показывающая, как использовать (в противном случае потенциально запутанный) метод со списком неявных параметров. Существование этой записи scaladoc можно проследить до этот печально известный вопрос.

person oxbow_lakes    schedule 04.04.2011
comment
Ясно... поэтому, поскольку я неправильно прочитал scaladoc (как указано ниже @Sciss), есть только версия, у которой есть аргумент, и поэтому сработало правило, согласно которому, если я использую скобки, я должен указать параметр. В противном случае, в других случаях API, если есть версия без аргументов, я мог бы использовать пустые скобки или без скобок. Это правильная оценка? - person Phuong LeCong; 05.04.2011
comment
@plecong - вы не можете использовать пустые скобки, если у метода нет списков параметров, но в остальном да, это правильно. - person oxbow_lakes; 07.04.2011

Есть только одна версия. Если вы внимательно посмотрите на API, запись без круглых скобок в начале говорит «[вариант использования]». Это искусственный дубликат записи в документах API, который упрощает понимание; записи вариантов использования в основном представляют собой сокращенные полные записи для некоторых распространенных сценариев. Подробнее об этом в этом вопросе: Scaladoc [вариант использования]

Причина, по которой второй вызов (...sum()) терпит неудачу, заключается в том, что хотя аргумент является неявным, он не имеет значения по умолчанию. Вы можете опускать аргументы в круглых скобках, только если указаны значения по умолчанию. Хотя это звучит нелогично, неявные аргументы обрабатываются по-разному: либо вы указываете их явно, тогда вам нужно использовать круглые скобки, либо вы опускаете их (потому что в области видимости находится неявное), но тогда вам также нужно отбросить круглые скобки. Это сделано для облегчения чтения, например.

def test(fun: Int => Int)(implicit s: String)

теперь вы можете писать test { i => i }, а не test(i => i)(), что неудобно.

person 0__    schedule 04.04.2011