Saturday, January 25, 2014

Why I like scala (part 1)

I bet many developers hate way Java has been evolving for many years. For instance resource safe cleanup feature. Java committee still were discussing, to add or not to add while C# already had nice language keyword using. You might say, Hey, Java 7 already has it. Right, however there are many others pending features that still wait to be added.

However I think that the problem is not only in Java committee. The problem is in language evolution and key grammar rules. Java is not scalable language. Almost every feature requires changes in Java grammar. So many keywords, and it might be greater. Jast take a look on C#. I love C# however number of keywords makes me dissapointed.

Well, there is another set of languages where there is no needs to modify grammar to add something interesting, moreover, there are languages which might create so high-level abstraction  that even their creaters could not expect such usage.These languages are C++, Haskell and Scala (this list is not complete).

Scala has no resoure safe cleanup feature and never won't. Because you can build it on your own.
Let's  develop this feature ourselves.

Version 1. (through dediated trait)
Lets use some trait Closable with just one operation close. Thus implementation might look like this:


trait Closable{
  def close(): Unit 
}

object Using {
}  
  def apply[A <: Closable, B](closeable:A) ( task : => B)  = {
      try {
        task
      } finally { closeable.disconnect }
  }
}

This version is simple and stratforward (just uses curring and parameters by name) however requires inheritance from Closable trait.

Here is usage example:

val resource : Closable = ... // take closable resource

Using(resource){
  // doing something with resource 
  // being confident that it will be closed
}

//ha-ha you can use it even this way
val resource2 : Closable = ...

val ret = Using(resource2){
  // return something meaningful
}

This implementation is simple however requires supporting Closable contract from all involved resources . You  might think that this is serious limitation. Well it is not true. Thanks to implicit boxing we can substitute any external resource with proper boxing object:

implicit def transform(r : InputStream) = new Closable{
  override def close(){
    r.close();
  }
}

val resource = new FileInputStream("/myfile")

Using(resource ){
  // read from resource resource 
}

Version 2. (through Duck typing)
 Scala has quite interesting feature anonimous structural types. New implementation based on structural types can accept any resource of any type (!) with only one requirement -  it should contain just close method inside.
object Using {
  
  def apply[A<:{ def close(): Unit; }, B](closeable:A) ( task : => B)  = {
      try {
        task
      } finally { closeable.disconnect }
  }
}
However despite that this approach is pretty attractive please be aware structural types are implemented via reflection, so it might affect performance a bit.

One more amazing example is synchronized sections. Java has special keyword synchronized. However for scala it is just ordinary method of AnyRef class.
God bless functions and parameters by name.




No comments: