2013-11-29 2 views
1

конкретно, в чем разница для двух следующих определений:чем разница между мимолетными параметрами() => T и просто T

def func(f:() => String) = f() 
    def func1(s: String) = s 

Я написал некоторые коды, чтобы проверить их, похоже, они производят то же самое результат; эти два определения одинаковы в этом сценарии; или у них есть какая-то разница?

var x = 1 

    def f() = { 
    x = x + 1 
    s"$x" 
    } 

    println(func1(f)) 
    println(func1(f)) 
    println(func1(f)) 

    println(func(f)) 
    println(func(f)) 
    println(func(f)) 

ответ

2

Они, возможно, одинаковы в этом сценарии, но есть много других сценариев, когда () => A и A сильно отличаются друг от друга. () => A называется thunk и используется для передачи части отложенного вычисления функции. Тело «thunk» не оценивается до тех пор, пока вызываемая функция не решит его оценить. Otherwitse, значение передаваемого аргумента оценивается вызывающим.

Рассмотрим пример, где есть разница между версией, которая принимает и преобразователь, версия, которая просто принимает значение:

object Thunk { 
    def withThunk(f:() ⇒ String): Unit = { 
    println("withThunk before") 
    println("the thunk's value is: " + f()) 
    println("now the thunk's value is: " + f()) 
    } 

    def withoutThunk(f: String): Unit = { 
    println("withoutThunk before") 
    println("now the value's value is: " + f) 
    } 

    def main(argv: Array[String]): Unit = { 
    withThunk {() ⇒ println("i'm inside a thunk"); "thunk value" } 
    println("------------") 
    withoutThunk { println("i'm not inside a thunk"); "just a value" } 
    } 
} 

Эта программа продемонстрирует некоторые различия. В версии thunk вы видите, что «withThunk before» печатается до того, как в первый раз «i'm in the thunk» печатается, который печатается дважды, так как f() оценивается дважды. В версии, отличной от thunk, «Я не внутри thunk» печатается до «withoutThunk before», так как это оценивается перед отправкой функции в качестве аргумента.

1
def func(f:() => String) = f() 

Этот принимает в качестве параметра функцию, которая возвращает строку.

def func1(s: String) = s 

Хотя это один простой требует строку в качестве параметра

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

1

Я хочу добавить пример использования () => String.

def printFuncResult(f:() => String) = println(f() + " " + f()) 

def ran =() => Math.random.toString 

printFuncResult(ran) 
printFuncResult(Math.random.toString) 

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

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

1
def func(f:() => String) = f() 
def func1(s: String) = s 

println(func1(f)) // in this case f is evaluated first, its value is used in func1. 

println(func(f)) // in this case f is NOT evaluated, but passed as it is to func. 
       // It is upto func to call f whenever needed, or even not call it. 

Именно это «ленивый» оценка F, что делает функ более полезным, например, е может быть передан в некоторых других функций высшего порядка, или он может быть вызван асинхронно.

Смежные вопросы