Hi! This blog is for news, announcements and questions regarding the
Mascara JavaScript compiler.

See also:
The online demo
Download latest release

Contact:
olav@olav.dk

Disclaimer:
ECMAScript is a trademark of Ecma International.

Powered by Squarespace
Thursday
Sep102009

Access modifiers in Mascara

Access modifiers (private and public) are among the most frequently requested features. They are now supported in the latest Mascara version, 1.2.4 (Download).

A private member is accessible only by methods in the same class. A public member is accessibly by everyone, just as members always are in classic JavaScript.

class A {
    public function famous() {};
    private function secret() {};
    private function test() {
         famous();  //OK because famous is public 
secret(); //OK because we are members of the same class
    }
}
var a = new A();
a. famous(); //OK
a. secret(); //ERROR, secret is not accessible from here

Members are public by default.

Static members can also be private. Private static methods can access private instance members in the same class and vice versa.

Constructors can also be private. With a private constructor it is not possible for other classes to create instances of the class. Static methods on the same class are then used to instantiate and return instances of the class. This can be used to implement patterns like singleton and factory.

Have fun with encapsulation!

Wednesday
Sep022009

Python 2.6 builds

Mascara is now availably built for Python 2.6 (the latest, recommended version of Python). Versions built for Python 2.5 is still available. If you dont know which Python version you have, you most probably have Python 2.6.

Download here.

Sunday
Aug232009

Getters and setters

Mascara has supported getter and setter functions and methods for some time, but in anticipation of the forthcoming ECMAScript 5 standard it has now added support for getters and setters in object literals.

In short, getters and setters are special functions which are invoked the same way a variable or property is read or assigned.

Here is an example of a getter:

//defining a getter function x
function get x() { return 7; }
// the function is invoked by accessing the variable value:
var a = x; // (a is assigned the result of calling get x, i.e. 7)

This is pretty useful for encapsulating member access.  A setter is the corresponding function which emulates assigning a value to a property or variable:

function set x(x) { alert(x) }
x = “hello”; // set x is invoked and shows
an alert box with “hello”

Getters and setters (together known as “accessors”) are useful for various forms of encapsulation. For example we can perform validation on input, we can change the internal representation without changing the interface, or we can trigger events when a property is changed.

Getters and setters often appear together, but we can emulate read-only properties by only providing a getter, or (less commonly) write-only properties by just exposing a setter.

The new addition is that ECMAScript 5 defines a syntax for gettes and setters in object literals. Example:

var ecoStorage = {
// to save memory space we only save half the value
_storage : 0.0,
get x() { return ecoStorage._storage * 2; },
set x(value) { ecoStorage._storage = value / 2 }

};
ecoStorage.x = 100;

var y = ecoStorage.x;
// y is assigned 100

So the accessors appear in the place of a name:value pair in an object literal.

Above we get a single object instance with the getter/setter pair. If we want to instiate multiple object, we have to create a constructor the object literal as a prototype. Hence:

function EcoStorage() {}
EcoStorage.prototype = {
_storage : 0,

get x() { return this._storage * 2; },
set x(value) { this._storage = value / 2 }

};

var storage1 = new EcoStorage;

storage1.x = 100;
var y = storage1.x; // y is assigned the value 100

This approach is also supported in Mascara, however I can’t say I find the syntax particularity attractive. I appreciate the flexibility declaring prototypes explicitly, but the syntax is not elegant.

The idiomatic way to do the same in Mascara is to use classes:

class EcoStorage {
var _storage : double = 0;
function get x() { return _storage * 2; }
function set x(value) { _storage = value / 2; }

}
var s = new EcoStorage;
s.x = 100;

Note the slightly different syntax (function get instead of just get) for getters/setter when they appear outside of object literals.

The ECMAScript 5 spec only allows getters and setters in object literals. However there is a low-level way to defining getters and setters through the new Object.defineProperty() method. This requires support in the JavaScript engine and is therefore not available in Mascara. It is not necessaray either, since Mascara supports the more straightforward syntax shown above.

Getters/setters in classes and as stand-alone functions has been supported in Mascara for a while. The ES5 compliant syntax for getters/setters in object literals is new in Mascara 1.2

Have fun!

Wednesday
Aug192009

Mascara 1.2 - With interfaces

Mascara 1.2 has been released, and supports interfaces, an often requested feature.

They work as you would expect very much like interfaces in Java and C#. Basically they describe a set of methods that any class that implements the interface must provide implementations for.

Interfaces may contain function and getter/setter declarations, but not variables or nested types. (Hence ECMAScript interfaces does not allow constants as in Java). Declaration are just function signatures without a body.

Example:

interface Moveable {
  function moveTo(x: int, y:int) : void;
}

class DialogBox implements Moveable {
    function moveTo(x : int, y:int) : void {
// implementation
}
}

Interfaces can inherit from multiple other interfaces, and classes can implement multiple interfaces.

Syntax is defined in the documentation.

Sunday
Aug092009

Arrays and higher-order functions in the type system

Lets look closer at how types are handled in Mascara in relation to Arrays and higher-order functions. This provides an interesting view into the type system.

Since this is not a general introduction to parameterized types, it is probably best understood if you already knows parameterized types, e.g. from Java or C# (where they are called "generics", but otherwise looks a lot the same.)

An Array can by default contain values of any type. However, an array can also be instantiated with a type parameter:

var x = new Array.<int>

This creates a new array which may only contain integer values.
If you initialize with an array literal like this:

var x = [1,2,3]

The compiler will determine the Array type from the initial values. In this case it will assume an array if integers, ie. Array.<int>, because all of the items are integers.

The Array class is declared like this:

dynamic class Array.<T> { ... methods ... }

The T is the type parameter which represent the type of the items. when a new array is constructed, the type parameter T is initialized with a concrete type.

Usually the compiler requires you to explicitly provide type arguments. However Array is special-cased (for backwards compatibility), so that when it is initialized without a type argument, it defaults to use the “star” type argument, which is the "anything goes" type.

Hence new Array gets translated into new Array.<*>.

[Aside: dynamic is a modifier which indicates than any property can be attached to the object at runtime without the compiler complaining. This is supported for backwards compatibility]

Now let’s look at the type signature for every:

function every(callbackfn:(function(item:T, ix:int):boolean)) : boolean {...}

This signature may seem daunting because of the nested function signature. every takes one argument, callbackfn which is in turn a function which takes two arguments.

The first argument to the callback function is a list item, hence its type is T, the type parameter for the Array. Hence if the list is a list of ints, the function has to take an int as the first argument.

The second argument to the callback is the index of the current item in the array. This is sometimes useful to have, but we may choose to ignore this argument as we have done in the examples above.

There is a certain amount of flexibility in what callback functions can be supplied. For example, as we have seen above, arguments can be ignored/left out. However we cannot supply a function with more required parameters than the signature expects.

The parameters may be more accepting than what is declared. For example we can provide a function which expects a double as the item type:

[1,2,3].every(function(x:double) x / 2 > 2)

This will work even though T is int, since int is a subset of double. (Technically parameters are said to be contravariant.) This is allows us to supply a function without type annotations on the parameters, which is pretty nice, especially for backwards compatibility.
The return value of the callback has to be a boolean as declared. However, in the above case the compiler can figure out on its own that the callback returns a boolean, because the result of a comparison is always a boolean.

Next, lets look at filter:

function filter(callbackfn:(function(item:T, ix:int):boolean)) : Array.<T> {...}

The parameters for the callback function are the same as above. The result type is itself a parameterized type - the same as the original array. Recall that T is defined as a type parameter for Array.

Hence if you filter an array of stings, the result is always a new array of strings (although the resulting list may be empty, the type is still Array.).

Now the most complex of the function signatures, map:

function map.<Q>(callbackfn:(function(item:T, ix:int):Q)) : Array.<Q> { ... }

Note that the function takes a type parameter, which must match the result type of the supplied function, and which also determines the type the resulting array.

Hence, an explicitly typed invication of map:

x.map.<string>(function(x)x.toString()) --> results in an array of type Array.<string>
x.map.<double>(function(x) x*2) --> results in an array of type Array.<double>

Obviously, if there is a mismatch between the type parameter and the return type of the function, you get a complaint from the compiler

x.map.<int>(function(x) x.toString()) --> compiler whines!

Now, here is the nice part: The type parameter to the function can be left out, since the compiler can infer the type from the type of the supplied function.

E.g.

x.map(function(x) x.toString()) --> results in an array of type Array.<string>, no complaints from the compiler

Of course the type argument makes it explicit what type you expect, and it may help catch type errors. On the other hand you save a bit of typing when calling the method by relying on the inference.

Again, this is a question of preference. I just like that you can write in a "typeless" manner, and then later turn it into more explicitly typed code.

As shown we can get pretty far in a type safe manner without specifying types explicitly. But consider this example:

[1,2,3].map(function(x) x*2)

This function will return an array of doubles, not an array of integers which you might expect. The reason is that the parameter to the callback is not specified, so the compiler has to be cautious. Multiplication is only guaranteed to return a double (since we consider int a subset of double).

An even worse example:

[1,2,3].map(function(x) x+2)

Here we get a compiler warning, because + can be used on anything, but has different meanings depending on the types of input.

Of course we can choose to ignore the warning. But it is better style to annotate the parameters:

[1,2,3].map(function(x:int) x+2)

This results in an array of integers.

Now you may wonder why the compiler can't infer the types in this case, since it is pretty obvious for us that the function will only be called with integers. However in the general case, the compiler cannot infer the types of function parameters, since there in no general solution for that. (Future versions of Mascara might attempt to infer function parameter types, but I doubt it will be possible in all cases.)

Therefore the general advice is to at least type-annotate function parameters. Typically the compiler will then be able to figure out the rest (e.g. local variables and return value).

The flamewars have raged for decades between proponents of static and dynamic typing. My experience is that static and explicit typing is a drag when experimenting and prototyping, however the bigger and more complex a project becomes, the more valuable static analysis becomes. I really likes that Mascara allows you to begin with dynamic and implicit typing, and then gradually add static guarantees as you find it appropriate.