A cute Scala hack

class ErrRef[S](s : S){
  private[this] var contents : Either[Throwable, S] = Right(s);

  def update(value : =>S){
    contents = try { Right(value) } 
              catch { case (e : Throwable) => Left(e) }
  }

  def apply() = contents match {
    case Right(s) => s;
    case Left(e) => throw e.fillInStackTrace();
  }
}

object ER{
  def apply[S](s : S) = new ErrRef(s);
}

And using it...

scala> ER(1)
res0: ErrRef[Int] = ErrRef@a96606

scala> res0()
res1: Int = 1

scala> res0() = 3

scala> res0()    
res3: Int = 3

scala> res0() = { println("Hello world"); 3} 
Hello world

scala> res0()                               
res5: Int = 3

scala> res0() = error("Lets see what happens here...")

scala> res0()
java.lang.RuntimeException: Lets see what happens here...
    at ErrRef.apply(RefExcept.scala:11)
    at .(:6)
    at .()
    at RequestResult$.(:3)
    at RequestResult$.()
    at RequestResult$result()
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAcc...
scala> res0() = throw new IllegalArgumentException("Go away")

scala> res0()
java.lang.IllegalArgumentException: Go away
    at ErrRef.apply(RefExcept.scala:11)
    at .(:6)
    at .()
    at RequestResult$.(:3)
    at RequestResult$.()
    at RequestResult$result()
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorI...

Comments

Ian Clarke on 2008-09-11 16:52:02:

This could just just a hint more explanation.

DavidLG on 2008-09-12 14:56:22:

Combining “update” with pass-by-name! Also an elegant user of Either. Cool.

david on 2008-09-12 19:22:19:

Ian: Nah, not really.