When to use call-by-name and call-by-value?

后端 未结 5 1874
悲哀的现实
悲哀的现实 2021-02-03 13:15

I understand the basic concept of call-by-name and call-by-value, and I have also looked into handful number of examples. However, I am not very clear about when to use call-by-

5条回答
  •  无人共我
    2021-02-03 14:00

    Call by name means the value is evaluated at the time it is accessed, while with call by value the value is evaluated first and then passed to the method.

    To see the difference, consider this example (completely non-functional programming with only side effects ;) ). Say you want to create a function which measures how much time some operation takes. You can do it with call-by-name:

    def measure(action: => Unit) = {
        println("Starting to measure time")
        val startTime = System.nanoTime
        action
        val endTime = System.nanoTime
        println("Operation took "+(endTime-startTime)+" ns")
    }
    
    measure {
        println("Will now sleep a little")
        Thread.sleep(1000)
    }
    

    You will get the result (YMMV):

    Starting to measure time
    Will now sleep a little
    Operation took 1000167919 ns
    

    But if you change only the signature of measure to measure(action: Unit) so it uses pass-by-value, the result will be:

    Will now sleep a little
    Starting to measure time
    Operation took 1760 ns
    

    As you can see, the action is evaluated before measure even starts and also the elapsed time is close to 0 due to the action already having been run before the method was called.

    Here, pass-by-name allows the expected behavior of the method to be achieved. In some cases it doesn't influence the correctness, but does influence the performance, for example in logging frameworks where a complex expression might not need to be evaluated at all if the result is not used.

提交回复
热议问题