Programming in Scala Gist 9

Vinu Charanya
vTechNotes
Published in
5 min readMay 28, 2016

These are the key points from the Programming in Scala, Second Edition by Martin Odersky, Lex Spoon, Bill Venners. I wanted to make note of some key points. They may seem broken and not make much sense, if you have not read the book. This is for personal reference. Feel free to correct me if I have interpreted anything wrong in this post.

Chapter 9— Control Abstraction

Let us see an example of how we can reuse key things learnt from gist 8.

9.1 Reduce code duplication

  • Functions are separated into common and non-common parts. A function value can be supplied as an argument, and the invoked function will in turn invoke the passed function value.
  • higer-order functions: functions that take functions as params — enables to create control abstraction that allows to reduce code duplication.
  • Eg., Write an API that allows to search for files matching a criterion. Criterion can be as follows:
FileMatcher with different criterion
  • Pass a function value to reduce some code duplication (looping through and yielding).
Using placeholder syntax with function literal _.endsWith(_)
More refactoring: The query getting passed to filesMatching is redundant.
  • Thus, _.endsWith(_) uses two bound variables and no free variables, whereas the function literal _.endsWith(query) contains one bound variable (arg _) and one free variable named query. Scala’s support for closures made it possible to remove the query param.

9.2 Simplify client code

  • Another important use of higher-order functions is to put them in an API itself to make client code more concise.
Check whether a list contains a negative number
Check whether a list contains an odd number
  • A lot of the code is repetitive which can be simplified with a control abstraction by calling the higher-order function exists on the passed List as follows:
Using exists for List containing odd number
Using exists for List containing odd number

9.3 Currying

  • Currying: A way to write functions with multiple parameter lists. For instance def f(x:Int)(y: Int) is a curried function with two parameter lists. A curried function is applied by passing several arguments lists, as in: f(3)(4). However, it is also possible to write a partial application of a curried function, such as f(3).
listing 9.3 illustration of currying process
  • The curried function can also be used with placeholder notation to form a partially applied function expression
underscore is the place holder for the second parameter list.
  • Since curriedSum(1)_ is not a legal function of scala, the need for space like println _ is not necessary here.

9.4 Writing new control structures

  • By creating methods that takes functions as arguments, one can effectively make new control structures.
Twice control structure that repeats an operation two times
  • op in the above example is a function that takes one Double as an argument and returns another Double.
  • A control pattern repeated in multiple parts of your code is a good signal to implement a new control structure.
  • Eg of a widely used coding pattern, open a resource, operate on it and then close the resource. This can be captured in a control abstraction.
new control structure for open a resource, operate on it and then close the resource.
  • The above technique is called “loan pattern” because the above control abstraction function, opens a resource and loans it to a function.
  • Any method invocation in Scala with exactly one argument, curly braces {} can be used instead of parenthesis ().
  • The ability to substitute curly braces for parentheses enables client to write programs that take function literals between curly braces making the method call feel more like a control abstraction.

How to make withPrintWriter feel more like control abstraction?

  • Since withPrintWriter takes arguments, it cannot use curly braces. However, the function passed is the last argument of the method.
  • Currying can be used to pull the first argument in the list, which will leave the op parameter as the lone parameter of the second argument list.
Currying makes withPrintWriter feel more like a control structure
  • With a more pleasing syntax withPrintWriter feels like a control structure.

9.5 By-name parameters

  • In the above example, withPrintWriter needs an argument “writer =>”. To implement a control structure with no value passed through curly brace.
  • To make a by-name parameter, give the parameter a type starting with => instead of ()=>.
  • The above myAssert’s parameter can be changed from “() => Boolean” into “=> Boolean”
by-name parameters used to achieve the myAssert(5 > 3) preferred syntax call
The difference between using (predicate: Boolean) and (predicate: => Boolean)
  • The expression inside the parentheses is evaluated before the call to boolAssert and the yielded result is passed to boolAssert.
  • The type of byNameAssert’s predicate parameter is => Boolean, the expression is not evaluated before the call to the method as in the example above.

Conclusion

  • Scala has rich function support to build control abstractions
  • Common control patterns should be factored out and take better advantage of higher-order function to reuse control patterns.
  • Currying and by-name parameters can be used to create higher-order functions with concise syntax.

--

--