Prefix - Arrays

Tuesday, September 20th, 2011     #javascript #everything

Prefix now supports arrays and starts to diverge from C#/.NET a little...

This post is about Prefix a modern language that compiles to JavaScript. A language where C# is the inspiration - not the goal. Read more on the Prefix Project Page.

Arrays

The recent focus with Prefix has been to get to the point where it can support JavaScript arrays. As mentioned in my previous post this involved support for generics, indexers, readonly properties and variadic parameters. What I didn't mention is that although I've added support for compiling all these features from Prefix to JavaScript, for arrays I only needed the ability to declare these constructs - since JavaScript provides the actual array implementation.

Arrays in Prefix are a little different to C# arrays. First, they're implemented as a generic class - Array<T>, as opposed to a type handled in the language itself. Second, since they wrap up the JavaScript array class they can be resized and behave more like a C# List.

So here's the built in declaration of the Array class:

extern class Array<T> : Object
{
    extern readonly int length;
    extern T this[int index] { get; set; }
    extern string join();
    extern string join(string separator);
    extern T pop();
    extern int push(T x);
    extern void reverse();
    extern T shift();
    extern int unshift(T x);
    extern Array<T> slice(int start);
    extern Array<T> slice(int start, int end);  
    extern Array<T> splice(int index, int howmany);
    extern Array<T> splice(int index, int howmany, T insert);
    extern Array<T> concat(Array<T> other_array);
    extern Array<T> concat(params Array<Array<T>> arrays);
    extern int push(params T[] x);
    extern int unshift(params T[] x);
    extern Array<T> splice(int index, int howmany, params T[] insert);
}

It simply declares the standard array manipulation functions. You'll notice there's no declaration for indexOf - since it's not supported in IE's JavaScript engine - I still need to figure out a nice way to normalize those sorts of quirks.

Although the Array type is a generic class the compiler also supports some syntactic sugar to make it look more traditional - any type suffixed with [] gets converted to an array generic. eg: string[] is identical to Array<string>

Using the array class is pretty much as you'd expect and looks very similar to standard JavaScript:

{{C#}}
extern dynamic Console;

var x = new string[];
x.push("Hello");
x.push("World");
x.splice(1, 0, "There");

for (int i=0; i<x.length; i++)
    Console.WriteLine(x[i]);
{{JavaScript}}
(function() {

// Start Global Code
var x=[];
x.push("Hello");
x.push("World");
x.splice(1, 0, "There");
for (var i=0; i<x.length; i++)
  Console.WriteLine(x[i]);

})();

Note:

  • instantiating a new array instance (new string[]) gets re-compiled into just [] (as any self-respecting JavaScript programmer would expect).
  • there's no size argument when instantiating an array (as opposed to C#)
  • even though the generated code looks almost exactly like the original the real benefit here is all the error checking the compiler is doing for you.
  • you can escape the type safety and revert to the wild world of dynamic with dynamic[] - which is essentially an untyped JavaScript array.
  • Prefix doesn't yet support the foreach statement, so enumerating an array is currently limited to an integer indexer. Collection enumeration via foreach will be coming soon.

What About .NET's List<T> Class?

It's at this point that I thought I'd be providing a compatible implementation of C#/.NET's List<T> class. After a lot of consideration though I felt this was the wrong approach - re-implementing the .NET runtime is not the point of this project.

There are a few cases where it would be great to compile the same code base under both C# and Prefix. Rather than trying to provide a Prefix implementation of many of the common .NET library functions I'm thinking of doing the opposite - providing a C# implementation of the Prefix runtime.

Of course if you really need List<T> you could always re-implement it yourself in Prefix code.

Next Up

I'm currently working on delegate support and have it mostly working - the current stumbling block is getting generic function type inference working with generic delegate parameters... but more about that later.

« Older - Prefix - Delegates Newer - Prefix - Generics (again), indexers, read only fields, variadic parameters »