В чем разница между def foo = {} и def foo() = {} в Scala?
Учитывая следующие конструкции для определения функции в Scala, можете ли вы объяснить, в чем состоит разница, и каковы будут последствия?
def foo = {}
против.
def foo() = {}
Update
Спасибо за быстрые ответы. Это здорово. Единственный вопрос, который остается для меня:
Если я опускаю скобку, есть ли способ передать функцию вокруг? Это то, что я получаю в repl:
scala> def foo = {}
foo: Unit
scala> def baz() = {}
baz: ()Unit
scala> def test(arg: () => Unit) = { arg }
test: (arg: () => Unit)() => Unit
scala> test(foo)
<console>:10: error: type mismatch;
found : Unit
required: () => Unit
test(foo)
^
scala> test(baz)
res1: () => Unit = <function0>
Обновление 2012-09-14
Вот некоторые похожие вопросы, которые я заметил:
Ответы
Ответ 1
Если вы включаете круглые скобки в определение, вы можете опционально опустить их при вызове метода. Если вы опустите их в определении, вы не сможете использовать их при вызове метода.
scala> def foo() {}
foo: ()Unit
scala> def bar {}
bar: Unit
scala> foo
scala> bar()
<console>:12: error: Unit does not take parameters
bar()
^
Кроме того, вы можете сделать что-то подобное с функциями более высокого порядка:
scala> def baz(f: () => Unit) {}
baz: (f: () => Unit)Unit
scala> def bat(f: => Unit) {}
bat: (f: => Unit)Unit
scala> baz(foo)
scala> baz(bar)
<console>:13: error: type mismatch;
found : Unit
required: () => Unit
baz(bar)
^
scala> bat(foo)
scala> bat(bar) // both ok
Здесь baz
будет принимать только foo()
, а не bar
. Какая польза от этого, я не знаю. Но это показывает, что типы различны.
Ответ 2
Позвольте мне скопировать мой ответ, который я разместил на дублированном вопросе:
A Scala метод 0-арности может быть определен с круглыми скобками или без них ()
. Это используется, чтобы сигнализировать пользователю о том, что метод имеет какой-то побочный эффект (например, распечатывать или удалять данные), в отличие от того, который отсутствует, который впоследствии может быть реализован как val
.
См. Программирование в Scala:
Такие безпараметрические методы довольно распространены в Scala. Напротив, методы, определяемые пустым скобками, например def height(): Int, называются пустыми методами. Рекомендуемое соглашение заключается в использовании безпараметрического метода, когда нет параметров, и метод обращается к изменяемому состоянию только путем чтения полей содержащего объекта (в частности, он не изменяет изменяемое состояние).
Это соглашение поддерживает принцип единого доступа [...]
Подводя итог, рекомендуется, чтобы стиль в Scala определял методы, которые не принимают никаких параметров и не имеют побочных эффектов в качестве безпараметрических методов, т.е. оставляют пустые круглые скобки. С другой стороны, вы никогда не должны определять метод, который имеет побочные эффекты без круглых скобок, потому что тогда вызовы этого метода будут выглядеть как выбор поля.
Ответ 3
Чтобы ответить на второй вопрос, просто добавьте _
:
scala> def foo = println("foo!")
foo: Unit
scala> def test(arg: () => Unit) = { arg }
test: (arg: () => Unit)() => Unit
scala> test(foo _)
res10: () => Unit = <function0>
scala> test(foo _)()
foo!
scala>