User Tools

Site Tools


blog:scala_objects_can_be_functions

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

blog:scala_objects_can_be_functions [2021/01/20 23:45] (current)
djo created
Line 1: Line 1:
 +====== Scala objects can be functions ======
 +
 +**Note:** This is adapted from my open-source work on Rally'​s //​[[https://​github.com/​rallyhealth/​scala-bootcamp/​blob/​master/​bootcamp/​snippets/​objects-can-be-functions.md|Scala Bootcamp]].//​
 +
 +===== A function === object with an `apply` method =====
 +
 +The following examples illustrate how Scala functions are objects and objects (with `apply` methods) are functions. ​ These aren't all idiomatic usage and don't illustrate all the ways to express function objects.
 +
 +They are offered with the following objectives:
 +
 +1. To teach the main ways Scala "​views"​ functions--as gerunds: nouns that are "​verbed"​.
 +
 +2. To introduce the concept of "​function factories"​--methods or functions that return new functions.
 +
 +==== The examples ====
 +
 +Class instances can be functions
 +
 +<code scala>
 +{
 +  class Square { def apply(x: Double) = x * x }
 +  val sqr = new Square
 +  sqr(5.0)
 +}
 +// res0: Double = 25.0
 +</​code>​
 +
 +Writing functions as class instances is usually more useful when a constructor holds a parameter value constant.
 +
 +<code scala>
 +{
 +  class Greeter(greeting:​ String) { def apply(who: String) = println(greeting + " " + who) }
 +  val greet = new Greeter("​Howdy"​)
 +  greet("​Slink"​)
 +  greet("​Woody"​)
 +  greet("​Buzz"​)
 +}
 +// Howdy Slink
 +// Howdy Woody
 +// Howdy Buzz
 +</​code>​
 +
 +When there is no need for a parameter to be held constant (as in the first example), we can use a singleton object.
 +
 +<code scala>
 +{
 +  object sqr { def apply(x: Double) = x * x }
 +  sqr(5.0)
 +}
 +// res2: Double = 25.0
 +</​code>​
 +
 +Or you can use anonymous function syntax (which is a bit more concise) to define a function that is also an object. ​ (Int => Int is the function'​s type; it just says the function accepts an Int and returns an Int.)
 +
 +<code scala>
 +{
 +  val sqr = (x: Int) => x * x
 +  println(sqr(5))
 +  println(sqr.apply(3))
 +}
 +// 25
 +// 9
 +</​code>​
 +
 +A function object defined using anonymous function syntax also automatically extends Scala'​s built-in Function1[A,​B] type, which provides other useful goodness that I'll let you look up.
 +
 +<code scala>
 +{
 +  val sqr = (x: Int) => x * x
 +  sqr.isInstanceOf[Function1[Int,​Int]]
 +}
 +// res4: Boolean = true
 +</​code>​
 +
 +And using generics along with the Numeric implicits from Scala'​s standard library, we can define `sqr` over all Numeric types.
 +
 +<code scala>
 +{
 +  import Numeric.Implicits._
 +
 +  def sqr[T: Numeric](x: T) = x * x
 +
 +  println(sqr(5))
 +  println(sqr(5.0))
 +}
 +// 25
 +// 25.0
 +</​code>​
 +
 +Stay tuned! ​ There'​s much more fun to come!
 +
 +==== Let's apply what we've learned ====
 +
 +(I suggest using [[https://​ammonite.io|Ammonite]] or a Scala Notebook application to quickly try *New Scala Things* and immediately see your results.)
 +
 +Here are a couple things to try based on what we learned above:
 +
 +1. Create a function `double` with the type signature `Int => Int` (in the same way we wrote `val sqr` above) that returns twice its argument. ​ Similarly, write a function named `plusOne` that (obviously) adds one to its argument value.
 +
 +2. We discussed one way to write function factories and we noted that functions created this way also have `Function1` as a supertype. ​ Let's play with this idea.  Two methods on `Function1` are `andThen` and `compose`. ​ Given `f1` and `f2` both of type T => T, these let us create a new function `f3` by writing `f1.compose(f2)` or `f1 compose f2`.  Using `double` and `plusOne` from above, play with `andThen` and `compose`. ​ What is their difference? ​ How might this technique be useful more generally?
 +
 +
 +
 +
  
blog/scala_objects_can_be_functions.txt ยท Last modified: 2021/01/20 23:45 by djo