I would like to have an implicit conversion with caching of the results (in a mutable map). However, when called implicitly, the map's getOrElseUpdate throws an exception. The following is a simplification of my real code (in particular, in my real code the conversion is not between Int and String).
import language.implicitConversions
import collection.mutable.{Map => MMap}
implicit val cache : MMap[Int, String] = MMap()
implicit def intToString(p: Int): String = cache.getOrElseUpdate(p, "number " + p.toString + " !" )
// Everything works fine in the following line,
// "false" is printed and (2 -> "number 2 !") is added to cache as expected
println(intToString(2).startsWith("whatever"))
// But when intToString is called implicitly, as in the line below, an exception is thrown
println(3.startsWith("whatever")) // But here, surprisingly, an exception is thrown
The exception message is:
java.lang.ExceptionInInitializerError
at at.logic.skeptik.Main.main(Main.scala)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
Caused by: java.util.NoSuchElementException: key not found: 3
at scala.collection.MapLike$class.default(MapLike.scala:228)
at scala.collection.AbstractMap.default(Map.scala:58)
at scala.collection.mutable.HashMap.apply(HashMap.scala:63)
at at.logic.skeptik.Main$.<init>(Main.scala:55)
at at.logic.skeptik.Main$.<clinit>(Main.scala)
at at.logic.skeptik.Main.main(Main.scala)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
java.lang.RuntimeException: Nonzero exit code: 1
at scala.sys.package$.error(package.scala:27)
Is this a bug of the Scala (2.10.0-M5) language? It seems to me that getOrElseUpdate tries something and catches an exception if the key is not found, but for some reason the exception is escaping the catch when the call to getOrElseUpdate is made from within an implicitly called implicit conversion...
Or is this expected behavior? If so, what should I do to make getOrElseUpdate work also from within an implicit call?
I would also be happy to hear any alternative idea for implementing an implicit converter that caches and reuses the conversions.
Best regards,
Bruno