Use of Scala by-name parameters

后端 未结 4 1913
臣服心动
臣服心动 2020-12-20 22:43

I am going through the book \"Functional Programming in Scala\" and have run across an example that I don\'t fully understand.

In the chapter on strictness/laziness

4条回答
  •  北荒
    北荒 (楼主)
    2020-12-20 23:13

    First, you are assuming that => A and () => A are the same. However, they are not. For example, the => A can only be used in the context of passing parameters by-name - it is impossible to declare a val of type => A. As case class parameters are always vals (unless explicitly declared vars), it is clear why case class Cons[+A](h: => A, t: => Stream[A]) would not work.

    Second, just wrapping a by-name parameter into a function with an empty parameter list is not the same as what the code above accomplishes: using lazy vals, it is ensured that both hd and tl are evaluated at most once. If the code read

    Cons(() => hd, () => tl)
    

    the original hd would be evaluated every time the h method (field) of a Cons object is invoked. Using a lazy val, hd is evaluated only the first time the h method of this Cons object is invoked, and the same value is returned in every subsequent invocation.

    Demonstrating the difference in a stripped-down fashion in the REPL:

    > def foo = { println("evaluating foo"); "foo" }
    > val direct : () => String = () => foo
    > direct()
    evaluating foo
    res6: String = foo
    > direct()
    evaluating foo
    res7: String = foo
    > val lzy : () => String = { lazy val v = foo; () => v }
    > lzy()
    evaluating foo
    res8: String = foo
    > lzy()
    res9: String = foo
    

    Note how the "evaluating foo" output in the second invocation of lzy() is gone, as opposed to the second invocation of direct().

提交回复
热议问题