spacer spacer spacer

2007-08-01

Advice for the OpenLaszlo optimizer

Since the OpenLaszlo compiler does not do common-subexpression elimination, when you are trying to optimize things, pretend you are writing in 1985 C. Instead of:

if (d.c[d.f]) d.c[d.f]( sd )

say:

var f = d.c[d.f];
if (f) f(sd);

Even better, when you find yourself having to write a null check, ask yourself if it would be cleaner, simpler, and more efficient to have the variable you are referencing not be nullable. For instance, if a variable is an array, consider using an empty array for its initial value, rather than null. This is a time/space trade-off: if there are many operations on the array and the variable is almost always not null, it will be more efficient to use an empty array; if there are few operations and the variable is usually null, then not allocating the empty array is the better choice.

(In Javascript 2, you will have the option of declaring a variable to be of a particular type, and you will have the option of declaring whether or not that variable can also be null. If you declare it not to be nullable, then the compiler will give you a compile-time warning if it cannot prove that the variable is never null, and it will insert the appropriate runtime check for you.

// This can be null, you have to check before using
var uplinkArray: Array;

// This cannot be null, you have to give a valid initial value
var uplinkArray: Array! = new Array();

Even though we don’t yet support the type declarations, we can follow the pattern and be ready…)

08:49 | Link | Reply | Track

2007-04-19

Undefined redux

A reader from Maynard asks:

My understanding is that in js, if a variable is declared var foo, and then it is read without an explicit initializer or setter being called, the variable still has a value of undefined and an error is signaled. If that is so in all js dialects then I don’t see any reason why adding variable declarations [to a class declaration] should ever cause problems. I don’t see how it could affect inheritance, for example. Am I missing something?

Continue reading "Undefined redux"
07:02 | Link | Reply | Track

2007-02-04

Order in the code

A reader from San Mateo writes:

I expected this to print the words of my phrase in order. It did not. What gives?

lzx> words = "The quick brown fox".split(" ") 
«Array(4)#55| [The, quick, brown, fox]» 
lzx> for (var w in words) Debug.write(words[w]); 
fox 
brown 
quick 
The

Gentle reader,

for in iterates over the ‘keys’ of an object. An array is just an object that happens to have (mostly) numbers as keys (and auto-maintains a length property that is one larger than the largest numeric key).

An object is just a hash table, and there is no implicit order of elements of a hash table (Java has LinkedHashMap which preserves entry order for iteration, and TreeMap which sorts entry order for iteration, but Javascript is a simpler language).

If you want to iterate over an array’s entries in order, use for (var i = 0; i < array.length; i++).

lzx> for (w = 0; w < words.length; w++) Debug.write(words[w]); 
The 
quick 
brown 
fox

If you want to iterate over an object’s keys in a particular order, you have to pull the keys out into an array, sort that array, and then iterate over that array:

var keys = new Array();
foreach (var k in array) { keys.push(k); }
keys.sort(function (a, b) {
  return (a > b) - (a < b);
});
for (var i = 0; i < keys.length; i++) {
  Debug.format("%s -> %s\n", keys[i], array[keys[i]]);
}

The fact that any particular runtime iterates over object keys in any particular order reveals an implementation detail of their hashes, but if you write your code to depend on that you are setting yourself up for a fall. Most Javascript runtimes just happen to use particularly trivial hash implementations that give you the illusion the keys are iterated in order.

See also the yellow box caution here.

17:00 | Link | Reply | Track