This post is for those who come from Java world and who worked on Scala from time to time. I have worked on Scala almost 2 years right now, some very interesting features I have never met before in my job, probably because nobody in my team knew them, or they were scared to use them, or whatever the reason is. So, having not studied Scala before I was missing them. Now I will show you those with examples.

The APPLY and UPDATE method

Everyone knows that apply in the companion object can be use to create factories. This means we can remove the new keyword and generate new objects. Less known is that apply can be defined also in the companion class, and it is used by using the object with the same syntax of the arrays in Scala (theObject(args…) is invoking the method apply(args…) on the object). In the same way we can redefine the update method exactly as you would do for arrays. I give you an example:

  1. class ApplyAndUpdate private () {
  2.   private var internalString = ""
  3.   def apply(value: String): Boolean = value == internalString
  4.   def update(value: String): Unit = internalString = value
  5. }
  6. object ApplyAndUpdate {
  7.   def apply(initialVal: String): ApplyAndUpdate = {
  8.     val newObj = new ApplyAndUpdate()
  9.     newObj() = initialVal
  10.     newObj
  11.   }
  12. }
  13.  
  14. val newApplyAndUpdate = ApplyAndUpdate("Check")
  15. println("ApplyAndUpdate is Bubba? "+newApplyAndUpdate("Bubba"))
  16. println("ApplyAndUpdate is Check? "+newApplyAndUpdate("Check"))
  17. newApplyAndUpdate() = "Bubba"
  18. println("ApplyAndUpdate is Bubba? "+newApplyAndUpdate("Bubba"))
  19. println("ApplyAndUpdate is Check? "+newApplyAndUpdate("Check"))
  20.  
  21. // The result is:
  22. ApplyAndUpdate is Bubba? false
  23. ApplyAndUpdate is Check? true
  24. ApplyAndUpdate is Bubba? true
  25. ApplyAndUpdate is Check? false

 

As you can see the class has a private constructor with no arguments (if I had put the internalString as a parameter for the constructor, it would have been a val so I could not have changed its value), but we provide an apply method in the companion object for creating new objects (companions can access to private methods and values). This is used in val newApplyAndUpdate = ApplyAndUpdate(“Check”) line. But we also defined an apply method on the companion class, and this is the one used in the println to return a boolean. Moreover, the line newApplyAndUpdate() = “Bubba” is using the update method of the companion class.

Partially applied functions

This I honestly have seen used many times, but in one specific context. Basically, as everyone using Scala should know, in this language functions are first class citizens, you can define functions as if they were variable, and then apply them FROM the variable. But even more, you can define new functions variable who stored a partially applied function already defined. For example you can write:

  1. def sum(a:Int, b:Int, c:Int) = a+b+c
  2. val sum2 = sum(12, _:Int, _:Int)
  3. val sum3 = sum _

The method sum is a normal method that takes 3 parameters. If I want to store the method in a variable I can use the syntax of sum3, by using the underscore (here comes the context in which I saw it used many times: if you are doing like that in a context in which the compiler knows you are using a function, you can omit the underscore… think about a foreach in which you want to print all elements, you will write something like container.foreach(println) and in this case println is a partially applied function. Please note that if you are applying the function by passing one or more arguments (so, you are not using the generic underscore as in sum3) you need to specify the type of the other parameters like in sum2.

Closures

Again, also this is a very used features, but there is something to tell. Closures are those situations in which free variables of a method (those variables that are not bound to any parameter but that are used by a function being in scope) are related, during the execution of the method, to specific current values of the variable in the scope.

  1. val more = 0
  2. val mynewsum = (x: Int) => x + more
  3. {
  4.   val more: Int = more + mynewsum(more) // returns 0
  5.   val more = 1
  6.   more + mynewsum(more) // returns 2
  7.   {
  8.     val more: Int = more + mynewsum(more) // returns 0?
  9.   }
  10. }

In the method mynewsum the free variable more creates a closure when the method is applied. I tried it in the interpreter (so please note, in the above code I defined twice the value of more in the same block, but the interpreter is defining a new block for any command line, it’s the reason for which it worked). I feel weird the result of the second inner block, cause the redefinition of more I would expect that it would use the second definition, with more = 1, but it is using  more=0 and apparently, being recursive, this is because more is bound to itself and is defined as initially zero (try val example: Int = example in the interpreter) while the more in the inner function is bound to the topmost more, that in the interpreter cannot be changed (so it is still zero as well)

Ok, for this post is enough. I will write something more in the next one related to this topic.

Stay tuned!

Share