2

Скажем, во-первых, у меня есть эта функция:В Scala есть функция, которая выполняет вызов по имени параметра, отличного от функции, которая принимает другую функцию в качестве параметра?

def number5()={ 
     println("number 5 starting") 
     println("number 5 exiting") 
     5 
} 

И потом:

def giveMeCallByNameParameter(f: =>Int)={ 
     println("starting") 
     f 
     println("exiting") 
} 

Когда я называю это:

giveMeCallByNameParameter(number5) 

Я получаю этот результат:

starting 
number 5 starting 
number 5 exiting 
exiting 

А если у меня есть эта функция:

def giveMeAnotherFunction(f:()=>Int)={ 
     println("starting") 
     f() 
     println("exiting") 
} 

И я это называю:

giveMeAnotherFunction(number5) 

я получаю тот же результат:

starting 
number 5 starting 
number 5 exiting 
exiting 

Таким образом, они отличаются вообще? Помимо отличия от наличия или отсутствия скобки?

Если они не разные? Тогда почему у нас есть этот терминологический вызов по имени?

+0

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

ответ

3

Параметры имени-имени могут быть любым допустимым выражением. Функции также являются действительными выражениями, но только одним выражением.

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

Как бы то ни было, функции обладают таким же свойством, но опять же, как я сказал ранее, функции - это всего лишь один вид выражения, тогда как параметры by-name могут принимать любые допустимые выражения.

Отличный вариант использования для Побочным имени параметров в создании пользовательской функции Assert:

def byNameAssert(predicate: => Boolean) = 
    if (assertionsEnabled && !predicate) 
    throw new AssertionError 

Таким образом, вы можете отключить оценку заявленных условий, контролируя значение assertionsEnabled.

Если утверждения не включена, вы можете даже есть выражение, которое бы обычно бросают, не дают исключение:

byNameAssert(x/0 == 0)

Также отметим также, что выражение, x/0 == 0, не является функцией ! Параметры By-name могут принимать любое выражение, но откладывают их оценку до тех пор, пока не будет вызвана функция.

Надеюсь, это поможет!

+0

Я вижу, я могу сделать это: giveMeCallByNameParameter (5) с вызовом по имени. но какова его практическая ценность? – CuiPengFei

+0

Вы также можете использовать параметры by-name для реализации так называемых «ленивых» функций, как показано в этом ответе: http://stackoverflow.com/a/3566978/114359 –

+0

aha, это хороший пример, спасибо. – CuiPengFei

1

Разница, насколько мне известно, по крайней мере, в вашем примере.

+0

, то, похоже, только для того, чтобы увеличить путаницу, имея эту терминологию – CuiPengFei

+0

, есть ли другие примеры, которые могли бы показать разницу? – CuiPengFei

+0

@CuiPengFei Я уже задал этот вопрос, я думаю, что вам нужен пример, когда функция принимает аргументы. –

2

В этом примере пример выглядит одинаково. Но рассмотрим этот случай использования

giveMeCallByNameParameter(number5 * number5) 

Вы получите этот результат:

starting
number 5 starting
number 5 exiting
number 5 starting
number 5 exiting
exiting

Если вы пытались сделать то же самое на giveMeAnotherFunction, он не будет компилировать

scala> giveMeAnotherFunction(number5() * number5())
:10: error: type mismatch;
found : Int
required:() => Int
giveMeAnotherFunction(number5() * number5())

Вы должны отправить функция не только любое выражение

giveMeAnotherFunction(() => number5 * number5) 
0

Есть разница.

  • вызова по имени обрабатывается только при использовании его, также ожидать Значения
  • Функции, с другой стороны, это отображение не Значение

Таким образом, , так что вы меняете метод number5 на функцию, вы не можете использовать звонок по имени, но вы можете использовать в функции

def number5()={ 
    println("number 5 starting") 
    println("number 5 exiting") 
    5 
} 

def func:() => Int = number5 // change method to function 

def giveMeCallByNameParameter(f: =>Int)={ 
    println("starting") 
    f 
    println("exiting") 
} 

giveMeCallByNameParameter(func) //compilation error 

def giveMeAnotherFunction(f:()=>Int)={ 
    println("starting") 
    f() 
    println("exiting") 
} 

giveMeAnotherFunction(func) // this is fine 

Кроме того, причина, вы можете использовать метод в giveMeAnotherFunction, который нуждается в функции, потому, что ETA-расширение. Существует множество примеров использования таких карт, как map, foldLeft и т. Д.