diff --git a/tutorials/tour/_posts/2017-02-13-automatic-closures.md b/tutorials/tour/_posts/2017-02-13-automatic-closures.md deleted file mode 100644 index bfc47bce94..0000000000 --- a/tutorials/tour/_posts/2017-02-13-automatic-closures.md +++ /dev/null @@ -1,73 +0,0 @@ ---- -layout: tutorial -title: Automatic Type-Dependent Closure Construction - -disqus: true - -tutorial: scala-tour -categories: tour -num: 31 -next-page: annotations -previous-page: operators ---- - -Scala allows parameterless function names as parameters of methods. When such a method is called, the actual parameters for parameterless function names are not evaluated and a nullary function is passed instead which encapsulates the computation of the corresponding parameter (so-called *call-by-name* evalutation). - -The following code demonstrates this mechanism: - -```tut -object TargetTest1 extends App { - def whileLoop(cond: => Boolean)(body: => Unit): Unit = - if (cond) { - body - whileLoop(cond)(body) - } - var i = 10 - whileLoop (i > 0) { - println(i) - i -= 1 - } -} -``` - -The function `whileLoop` takes two parameters `cond` and `body`. When the function is applied, the actual parameters do not get evaluated. But whenever the formal parameters are used in the body of `whileLoop`, the implicitly created nullary functions will be evaluated instead. Thus, our method `whileLoop` implements a Java-like while-loop with a recursive implementation scheme. - -We can combine the use of [infix/postfix operators](operators.html) with this mechanism to create more complex statements (with a nice syntax). - -Here is the implementation of a loop-unless statement: - -```tut -object TargetTest2 extends App { - def loop(body: => Unit): LoopUnlessCond = - new LoopUnlessCond(body) - protected class LoopUnlessCond(body: => Unit) { - def unless(cond: => Boolean) { - body - if (!cond) unless(cond) - } - } - var i = 10 - loop { - println("i = " + i) - i -= 1 - } unless (i == 0) -} -``` - -The `loop` function just accepts a body of a loop and returns an instance of class `LoopUnlessCond` (which encapsulates this body object). Note that the body didn't get evaluated yet. Class `LoopUnlessCond` has a method `unless` which we can use as a *infix operator*. This way, we achieve a quite natural syntax for our new loop: `loop { < stats > } unless ( < cond > )`. - -Here's the output when `TargetTest2` gets executed: - -``` -i = 10 -i = 9 -i = 8 -i = 7 -i = 6 -i = 5 -i = 4 -i = 3 -i = 2 -i = 1 -``` - diff --git a/tutorials/tour/_posts/2017-02-13-by-name-parameters.md b/tutorials/tour/_posts/2017-02-13-by-name-parameters.md new file mode 100644 index 0000000000..6121e6ecc6 --- /dev/null +++ b/tutorials/tour/_posts/2017-02-13-by-name-parameters.md @@ -0,0 +1,40 @@ +--- +layout: tutorial +title: By-name Parameters + +disqus: true + +tutorial: scala-tour +categories: tour +num: 31 +next-page: annotations +previous-page: operators +--- + +_By-name parameters_ are only evaluated when used. They are in contrast to _by-value parameters_. To make a parameter called by-name, simply prepend `=>` to its type. +```tut +def calculate(input: => Int) = input * 37 +``` +By-name parameters have the the advantage that they are not evaluated if they aren't used in the function body. On the other hand, by-value parameters have the advantage that they are evaluated only once. + +Here's an example of how we could implement a while loop: + +```tut +def whileLoop(condition: => Boolean)(body: => Unit): Unit = + if (condition) { + body + whileLoop(condition)(body) + } + +var i = 2 + +whileLoop (i > 0) { + println(i) + i -= 1 +} // prints 2 1 +``` +The method `whileLoop` uses multiple parameter lists to take a condition and a body of the loop. If the `condition` is true, the `body` is executed and then a recursive call to whileLoop is made. If the `condition` is false, the body is never evaluated because we prepended `=>` to the type of `body`. + +Now when we pass `i > 0` as our `condition` and `println(i); i-= 1` as the `body`, it behaves like the standard while loop in many languages. + +This ability to delay evaluation of a parameter until it is used can help performance if the parameter is computationally intensive to evaluate or a longer-running block of code such as fetching a URL.