In the previous post I introduced the Ceylon JavaScript
              compiler project. One of the things I mentioned
              was that there was an extremely natural mapping from Ceylon
              to JavaScript making use of JavaScript's lexical scope to
              create nicely encapsulated JavaScript objects. For example,
              given the following Ceylon code:
              
              
              
              
              shared class Counter(Integer initialCount=0) {
    variable value currentCount:=initialCount;
    shared Integer count {
        return currentCount;
    }
    shared void inc() {
        currentCount:=currentCount+1; 
    }
}
              
              We produce the following JavaScript:
              
              var $$$cl15=require('ceylon/language/0.1/ceylon.language');
//class Counter at members.ceylon (1:0-9:0)
this.Counter=function Counter(initialCount){
    var $$counter=new CeylonObject;
    //value currentCount at members.ceylon (2:4-2:45)
    var $currentCount=initialCount;
    function getCurrentCount(){
        return $currentCount;
    }
    function setCurrentCount(currentCount){
        $currentCount=currentCount;
    }
    //value count at members.ceylon (3:4-5:4)
    function getCount(){
        return getCurrentCount();
    }
    $$counter.getCount=getCount;
    //function inc at members.ceylon (6:4-8:4)
    function inc(){
        setCurrentCount(getCurrentCount().plus($$$cl15.Integer(1)));
    }
    $$counter.inc=inc;
    return $$counter;
}
              
              Notice that this code is really quite readable and really
              not very different to the original Ceylon.
              
              Let's load this module up in the node REPL, and play with the
              Counter.
              
              > Counter = require('./node_modules/default/members').Counter
[Function: Counter]
> Integer = require('./runtime/ceylon/language/0.1/ceylon.language').Integer
[Function: Integer]
> c = Counter(Integer(0))
{ getCount: [Function: getCount], inc: [Function: inc] }
              
              The Counter instance presents a nice clean API with
              getCount() and inc() functions:
              
              > c.getCount().value
0
> c.inc()
> c.inc()
> c.getCount().value
2
              
              Notice that the actual value of $$counter is completely
              hidden from the client JavaScript code. Another nice thing
              about this mapping is that it is completely free of
              JavaScript's well-known broken this. I can freely use the
              methods of c by reference:
              
              > inc = c.inc
[Function: inc]
> count = c.getCount
[Function: getCount]
> inc()
> count().value
3
              
              Now, an issue that was bugging me about this mapping - and
              bugging Ivo even more - is the performance cost of this
              mapping compared to statically binding the methods of a class
              to its prototype. Ivo did some tests and found that it's up
              to like 100 times slower to instantiate an object that
              defines its methods in lexical scope instead of using its
              prototype on V8. Well, that's not really acceptable in
              production, so I've added a switch that generates code that
              makes use of prototypes. With this switch enabled, then for
              the same Ceylon code, the compiler generates the following:
              
              var $$$cl15=require('ceylon/language/0.1/ceylon.language');
//ClassDefinition Counter at members.ceylon (1:0-12:0)
function $Counter(){}
//AttributeDeclaration currentCount at members.ceylon (2:4-2:45)
$Counter.prototype.getCurrentCount=function getCurrentCount(){
    return this.currentCount;
}
$Counter.prototype.setCurrentCount=function setCurrentCount(currentCount){
    this.currentCount=currentCount;
}
//AttributeGetterDefinition count at members.ceylon (3:4-5:4)
$Counter.prototype.getCount=function getCount(){
    return this.getCurrentCount();
}
//MethodDefinition inc at members.ceylon (6:4-8:4)
$Counter.prototype.inc=function inc(){
    this.setCurrentCount(this.getCurrentCount().plus($$$cl15.Integer(1)));
}
this.Counter=function Counter(initialCount){
    var $$counter=new $Counter;
    $$counter.initialCount=initialCount;        
    return $$counter;
}
              
              Clearly this code is a bit harder to understand than what we
              started with. It's also a lot uglier in the REPL:
              
              > c = Counter(Integer(0))
{ initialCount: { value: 0, ... } }
              
              Notice that the internal state of the object is now exposed to
              clients. And all its operations - held on the prototype - are
              also accessible, even the non-shared operations. Finally,
              JavaScript's this bug is back:
              
              > inc = c.inc
[Function: inc]
> inc()
TypeError: Object #<error> has no method 'getCurrentCount'
    at inc (/Users/gavin/ceylon-js/build/test/node_modules/default/members.js:21:31)
    ...
              
              We have to use the following ugly workaround:
              
              > inc = function(){c.inc.apply(c,arguments)}
> inc()
> c.getCount().value
1
              
              (Of course, the compiler automatically inserts these wrapper
              functions when you write a function reference at the Ceylon
              level.)
              
              Personally, I don't really see why the JavaScript interpreter
              in V8 could not in principle internally optimize our original
              code to something more like our "optimized" code. I think it
              would make JavaScript a much more pleasant language to deal
              with if there wasn't such a big difference in performance
              there.
              
              Anyway, if you're producing your JavaScript by writing Ceylon,
              this is now just a simple compiler switch :-)