The importance of API design
Reflecting on the exercise leading up to yesterday's post, one of the things that struck me in the comparison of the .net Framework used from F# and the Java APIs available to Scala/JVM was how much the former got little details right to facilitate working in the web-page embedded context. Take the simple task of getting at the URL query parameters for the page in which the applet is embedded
In Silverlight, in the main UserControl
class:
let (success, stringValueLat) = System.Windows.Browser.HtmlPage.Document.QueryString.TryGetValue("lat") |
In an applet, where peer
is the Applet
instance:
// navigate methods returning type Object to get to the raw string URL | |
val win = JSObject.getWindow(peer) | |
val doc = win.asInstanceOf[JSObject].getMember("document") | |
val loc = doc.asInstanceOf[JSObject].getMember("location") | |
val url = loc.asInstanceOf[JSObject].getMember("href").asInstanceOf[String]; | |
// get minimal parsing assistance from the APIs, where java.net.URI is | |
// woefully underfunctional compared with System.Windows.Browser.HtmlDocument | |
val params = (new URI(url)).getQuery() | |
// Now split up the query string manually | |
// or could use parser APIs | |
var tmap = new Map[String, String]() | |
if (params ne null) | |
{ | |
val parts = params.split("&") | |
tmap = (tmap /: parts) ( (m:Map[String,String], pair:String) => | |
{ | |
val bits = pair.split("=") | |
val tuple : (String, String) = (bits(0), bits(1)) | |
m + tuple | |
}) | |
} | |
val stringValueLat = tmap.getOrElse("lat", "") |
Perhaps this just shows how the old-style Java applet has withered on the vine, while Silverlight as a competitor to Flash has taken on a more aggressive stance for developer acceptance -- but with the decade-plus that Java has under its belt compared with Silverlight's barely more than a year (1.0 not really counting), the comparison is rather disappointing.
I shall have to investigate whether the continued work on scala-msil has led to any material improvements in its robustness since I looked at it last, six months ago.
A few minutes later
Well, my six month old port of the Scala actors package to pure Scala calling the .Net APIs still blows the compiler up in a Scala 2.8 nightly that's just a few days old. The explosion is in pure Scala code taken directly from the 2.7.5 actors package, and not the Scala-calling-.net replacements I coded of the Java parts of that package:
object Eval$2 symbol = final caseobject Eval$2 owner = final object Futures with methods = List(scala.actors.Futures.Eval$2. , scala.actors.Futures.Eva l$2.readResolve, scala.actors.Futures.Eval$2.canEqual, scala.actors.Futures.Eval $2.productElement, scala.actors.Futures.Eval$2.productArity, scala.actors.Future s.Eval$2.productPrefix, scala.actors.Futures.Eval$2.toString, scala.actors.Futur es.Eval$2.productElements, scala.actors.Futures.Eval$2.productIterator) Exception in thread "main" java.lang.RuntimeException: ILGenerator.emit(): Stack underflow in method: public static System.Void scala.actors.Futures$+scala.acto rs.Futures.Eval$2$::.cctor() at ch.epfl.lamp.compiler.msil.emit.ILGenerator.emit(ILGenerator.scala:48 7)
So, still not ready for prime-time.