As I was saying the other day, CLR arrays and JScript arrays are totally different beasts. It is hard to imagine two things being so different and yet both called the same thing. Why did the CLR designers and the JScript designers start with the same desire — create an array system — and come up with completely different implementations?
Well, the CLR implementers knew that dense, nonassociative, typed arrays are easy to make fast and efficient. Furthermore, such arrays encourage the programmer to keep homogenous data in strictly bounded tables. That makes large programs that do lots of data manipulation easier to understand. Thus, languages such as C++, C# and Visual Basic have arrays like this, and thus they are the basic built-in array type in the CLR.
Sparse, associative, untyped arrays are not particularly fast but they are far more dynamic and flexible than Visual Basic-style arrays. They make it easy to store heterogeneous data in any table without worrying about picky details such as exactly how big that table is. In other words, they are “scripty”. Languages such as JScript and Perl have arrays like this.
JScript .NET has both very dynamic, scripty arrays and more strict CLR arrays, making it suitable for both rapid development of scripts and programming in the large. But like I said, making these two very different kinds of arrays work well together is not trivial.
JScript .NET supports the creation of multidimensional typed arrays. As with single-dimensional arrays, the array size is not part of the type. To annotate a variable as containing a typed multidimensional array the syntax is to follow the type with brackets containing commas. For example, to annotate a variable as containing a two dimensional array of Strings you would say:
var multiarr : String[,];
The number of commas between the brackets plus one is equal to the rank of the array. (By this definition if there are no commas between the brackets then it is a rank-one array, as we have already seen.)
A multidimensional array is allocated with the
new keyword as you might expect:
multiarr = new String[4,5]; multiarr[0,0] = "hello";
Notice that elements of typed arrays are always accessed with a comma-separated list of integer indices. There must always be exactly one index for each dimension in the array. You can’t use the ragged array syntax
There are certain situations in which you know that a variable or function argument will refer to a CLR array but you do not actually know the element type or the rank, just that it is an array. Should you find yourself in one of these (rather rare) situations there is a special annotation for a CLR array of unknown type and rank:
var sysarr : System.Array; sysarr = new String[4,5]; sysarr = new double;
As you can see, a variable of type
System.Array may hold any CLR array of any type and rank. However, there is a drawback. Variables of type
System.Array may not be indexed directly because the rank is not known. This is illegal:
var sysarr : System.Array; sysarr = new String[4,5]; sysarr[1,2] = "hello"; // ILLEGAL, System.Arrays are not indexable
Rather, to index a
System.Array you must call the
SetValue methods with an array of indices:
var sysarr : System.Array; sysarr = new String[4,5]; sysarr.SetValue("hello", [1,2]);
The rank and size of a
System.Array can be determined with the
Thinking about this a bit now, I suppose that we could have detected at compile time that a System.Array was being indexed, and constructed the call to the getter/setter appropriately for you, behind the scenes. But apparently we didn’t. Oh well.
Next time on FAIC: mixing and matching JScript and CLR arrays.
Commentary from 2021:
As I say rather a lot, design is the art of coming up with compromises, and of course a good compromise leaves everybody mad. I expected more pushback on these decisions; trying to make it all work in a manner that felt both true to JScript and made efficient use of CLR types designed for a statically-typed world led to a lot of compromises to be mad about. But it went over pretty well, insofar as JScript .NET went over anywhere at all.
There was some good discussion in the comments on the original post about how you might write a fold so that it worked on JScript arrays, CLR arrays, multidimensional arrays, and so on, and did so efficiently.