Showing posts with label scala. Show all posts
Showing posts with label scala. Show all posts

Thursday, November 21, 2013

Assert T

Here is some trick for getting over type erasure in Scala.


I want to create the following method that will expect an exception of particular type:

def assertT[T <: Throwable ](body: =>Unit) = {
  try {
    body
    assert(false)
  } catch {
    case e : T => assert(true)
  }
}

But due to type erasure, the case condition ( : T ) will be never checked. Scala compiler will warn you with "abstract type pattern T is unchecked since it is eliminated by erasure".

To fix this, you need a runtime class info and runtime class check:

def assertT[T <: Throwable : ClassTag](body: =>Unit) = {
  val clazz = implicitly[ClassTag[T]].runtimeClass
  try {
    body
    assert(false)
  } catch {
    case e if clazz.isInstance(e) => assert(true)
  }
}

where ClassTag is scala.reflect.ClassTag

Friday, September 21, 2012

Pearls of scala I - By-name parameters

In C# there is no way to define short-circuit evaluated 'and' function (for example).

The naive implementation like following is not good enough.

bool And(bool a, bool b){
  if (a)
    return b;
  else 
    return false;
}

Let define an identity function:


bool Id(bool value){
  Console.WriteLine(value);
  return value;
}


And let's compare output of the following statements:

And(Id(false),Id(false))    and    Id(false) && Id(false)

The first statement will produce:
False
False

The second one:
False

The second statement will not be fully evaluated. As far as first operand of && returns false, the statement evaluates to false regardless of second operand.

Instead the first one have to evaluate both parameters before evaluating the method body.

The only way to imitate the short-circuit evaluation is to pass ugly Action<bool> as a second parameter:


bool And(bool a, Action<bool> b){
  if (a)
   return b();
  else 
    return false;
}

var result = And(Id(false), ()=>Id(false));

In Scala, by-name parameters are part of language, so we could easily transform long-circuit 'and' function to  a short-circuit with minimum changes in function definition and without any changes in function usages:


Long-circuit:

def and(a:Boolean, b:Boolean) = if (a) b else false

Short-circuit:

def and(a:Boolean, b: => Boolean) = if (a) b else false

'=> Boolean' states for 'by-name' parameter, it would be evaluated only in function body as many times as requested (even zero, like in 'and(false,someLongFunction())')