So, I've started a parallel implementation of jinterface 1.5 in Scala, the idea being
- To teach myself Scala by doing
- To experiment with the actor-based concurrency as a counterparty to the Erlang model
- To experiment with Scala as a dual VM technology
So far, just the term-representation classes, and the start of the Input/Decode and Output/Encode part; and some unit tests, only for Atom so far.
I am impressed at how much I've been able to do without bringing in platform types that I will need to abstract out. What was memory-based I/O in Java or C# becomes Seq[Byte] or Queue[Byte] as appropriate and basing all exceptions off the shared name Exception root class gets rid of any dependence on concrete subclasses. It's only BigInt that is a known problem so far, where I'll need to factor out a platform abstraction later. Of course abstracting ZLib support is a task lurking in the near future, as well.
The first noticeable difference from trying to tidy the C#2 port of an older Java version is that the functional style and rich library support make a lot of previously long-winded support methods significantly more expressive. Contrast the Erlang list (of integer values) to String
public System.String StringValue
{
get
{
char[] body = new char[Arity];
ReadOnlyCollection<IObject> e = Elements;
for (int i = 0; i < Arity; ++i)
{
Integer v = e[i] as Integer;
if (null == v) body[i] = '?';
else
{
System.Diagnostics.Debug.Assert(v != null && v.Value != null);
char? c = v.Value.ToChar();
if (null == c) c = '?';
body[i] = (char)c;
}
}
return new string(body);
}
}
// and elsewhere
public char? ToChar()
{
try
{
return (char)System.UInt16.Parse(this.ToString(), System.Globalization.NumberStyles.Integer, System.Globalization.CultureInfo.InvariantCulture);
}
catch (OverflowException)
{
return null;
}
}
with
def AsString =
{
(Elements map List.AsChar).mkString
}
// and elsewhere
def AsChar(obj : IObject) =
obj match
{
case c : Integer if c.Value < (Integer.Zero + Char.MinValue.toInt) => '?'
case c : Integer if c.Value >= (Integer.Zero + Char.MaxValue.toInt) => '?'
case c : Integer => c.Value.intValue.toChar
case _ => '?'
}
Yes, using C#3's functional extensions, that too could be simplified; this is really the Java equivalent of doing that.
Code drop on the MediaFire page.