Функции без аргументов, с единицей в качестве аргумента в Scala - PullRequest
31 голосов
/ 05 мая 2010
 def foo(x:Int, f:Unit=>Int) = println(f())

foo(2, {Unit => 3+4}

//case1
def loop:Int = 7
foo(2, loop) //does not compile

changing loop to 
//case 2
def loop():Int = 7
foo(2, loop) // does not compile

changing loop to
//case 3
def loop(x:Unit): Int = 7 //changing according to Don's Comments
foo(2,loop) // compiles and works fine

не должен ли работать случай 1 и случай 2? почему они не работают?

определение foo как

def foo(x:Int, y:()=>Int)

тогда случай 2 работает, но не случай 1.

Не все они должны работать, так или иначе определяя функции.

// также я думаю () => Int в foo - плохой стиль, y: => Int не работает, комментарии ??

Ответы [ 3 ]

82 голосов
/ 05 мая 2010

Скала различает следующие вещи:

  • Функции / методы с без списков параметров («параметр по имени», если функция)
  • Функции с один пустой список параметров
  • Функции с одним параметром типа Единица измерения

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

Итак, даже если Unit записано (), это не совпадает с параметром аргумента parens () для функции или метода. Вместо этого думайте о () как о Tuple0.

Итак, если вы говорите f: Unit => Int, вы имеете в виду, что «f принимает один параметр, но это действительно скучный параметр, потому что это Unit, который всегда должен быть одинаковым Tuple0 значением ()» , То, что вы пишете, действительно коротко для f: (Unit) => Int.

Если вы говорите f: () => Int, то вы имеете в виду, что «f не принимает параметров и выдает Int».

Если вы говорите f: => Int, то вы имеете в виду, что «задержите выполнение любого оператора, получающего значение Int, до тех пор, пока мы не используем его в этом коде (и не переоцениваем его каждый раз)». С функциональной точки зрения это в основном совпадает с f: () => Int (и внутренне преобразуется в тот же класс Function0), но имеет другое использование, предположительно, для обеспечения более компактной формы замыканий (вы всегда опускаете => в коде вызова).

14 голосов
/ 05 мая 2010

() => Int - это функция0 [Int], а Unit => Int - это функция1 [Unit, Int]

scala> val function0: () => Int = () => 5
function0: () => Int = <function0>

scala> val function1: Unit => Int = u => 5
function1: (Unit) => Int = <function1>

scala> function0()
res0: Int = 5

scala> function1("anything")
res1: Int = 5

scala> function1(100)
res2: Int = 5

scala>

Также обратите внимание, что () является объектом Единицы

scala> function1(())
res11: Int = 5

scala> function1 ()
res12: Int = 5

scala> function1()
res13: Int = 5

scala> val unit = ()
unit: Unit = ()


scala> function1(unit)
res15: Int = 5

scala> function1 apply unit
res16: Int = 5

scala>
2 голосов
/ 05 мая 2010

В случаях 1 и 2, приведенных выше, возвращаемое значение loop вместо loop само проверяется типом для второго аргумента foo и завершается ошибкой: Int! = Unit => Int

Изменение на loop содержит опечатку.

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