Scala's lazy arguments: How do they work?

前端 未结 2 1761
盖世英雄少女心
盖世英雄少女心 2020-12-09 01:28

In the file Parsers.scala (Scala 2.9.1) from the parser combinators library I seem to have come across a lesser known Scala feature called \"lazy arguments\". Here\'s an exa

2条回答
  •  有刺的猬
    2020-12-09 02:16

    The wikipedia article for Scala even answers what the lazy keyword does:

    Using the keyword lazy defers the initialization of a value until this value is used.

    Additionally, what you have in this code sample with q : => Parser[U] is a call-by-name parameter. A parameter declared this way remains unevaluated, until you explicitly evaluate it somewhere in your method.

    Here is an example from the scala REPL on how the call-by-name parameters work:

    scala> def f(p: => Int, eval : Boolean) = if (eval) println(p)
    f: (p: => Int, eval: Boolean)Unit
    
    scala> f(3, true)
    3
    
    scala> f(3/0, false)
    
    scala> f(3/0, true)
    java.lang.ArithmeticException: / by zero
        at $anonfun$1.apply$mcI$sp(:9)
        ...
    

    As you can see, the 3/0 does not get evaluated at all in the second call. Combining the lazy value with a call-by-name parameter like above results in the following meaning: the parameter q is not evaluated immediately when calling the method. Instead it is assigned to the lazy value p, which is also not evaluated immediately. Only lateron, when p is used this leads to the evaluation of q. But, as p is a val the parameter q will only be evaluated once and the result is stored in p for later reuse in the loop.

    You can easily see in the repl, that the multiple evaluation can happen otherwise:

    scala> def g(p: => Int) = println(p + p)
    g: (p: => Int)Unit
    
    scala> def calc = { println("evaluating") ; 10 }
    calc: Int
    
    scala> g(calc)
    evaluating
    evaluating
    20
    

提交回复
热议问题