Introducing Augmented JavaScript

Today I’d like to introduce my latest project named “Augmented JavaScript” to the world.

What is Augmented JavaScript?

Augmented javascript is a javascript-preprocessor written in javascript. It’s function is similar to the more known javascript preprocessor CoffeScript, however, while CoffeScript has more or less invented a new language alltogether, Augmented JavaScript is a lot more similar to plain old JavaScript.

Currently Augmented JavaScript adds 3 new features to the JavaScript language. All of these features are new, and not very well tested, so bugs should be expected. These new features are:

  • Await
  • Yield
  • For..Of-Loops
  • Shorthand Function-Syntax

Await

The await-keyword is taken from the newer versions of C# and VB.NET. It’s job is to pause the execution of a piece of code untill new data is availible, and then continue off where it left. This results in the ability to write async functions very easily without the need for callback-nesting. For instance, let’s asume we have a “magic” function called load whos task it is to perform a simple xhr-request and callback when the data is availible. Using regular javascript one would in general write code such as this:

function login(username, password, cb) {
    getUser(username, password, function(user) {
        getGroups(user.id, function(groups) {
            cb({
                user: user,
                groups: groups
            });
        });
    });
}

function getUser(username, password, cb) {
    load('/getUser', {
        username: username,
        password: password
    }, function(data) {
        if(data.success) {
            cb(data.user);
        } else {
            cb(null);
        }
    });
}

function getGroups(userId, cb) {
    load('/getGroups/' + userId, function(data) {
        if(data.success) {
            cb(data.groups);
        } else {
            cb(null);
        }
    });
}

As you can see, there’s a lot of nesting of functions, and it’s not always easy to understand what is going to happen and in what order. People who are unused with javascript typically expect that when you’ve run the login-function, the user will be logged in immidiately, which isn’t the case because our load-function is async. Now, take a look at the same code rewritten to use Augmented JavaScript (here ofcause I assume that the load-function has been written in such a way that it is usable with the await-keyword and not just callbacks as in the previous example, more on that later).

function login(username, password) {
    var user = await getUser(username, password);
    var groups = await getGroups(user.id);
    return {
        user: user,
        groups: groups
    };
}

function getUser(username, password) {
    var data = await load('/getUser', {
        username: username,
        password: password
    });
    if(data.success) {
        return data.user;
    } else {
        return null;
    }
}

function getGroups(userId) {
    var data = await load('/getGroups' + userId);
    if(data.success) {
        return data.groups;
    } else {
        return null;
    }
}

Quite a bit easier to read, no? The result of these two snippets of code should theoretically be the same. However, as said, the probability of experiencing bugs in Augmented JavaScript is still fairly high, and I have not explicitly tested the snippets found here yet.

What is awaitable

Internally, Augmented JavaScript uses the exelent Q-library to handle waiting. That means that anything that can be understood by the Q-library, can be waited for.

Yield

The second new feature is the yield-keyword. The yield-keyword works in certain ways almost like the await keyword, with the exception that instead of waiting for whatever you pass after the yield-keyword it is returned to the calling function. The yield-keyword is simply put used to create generators (or iterators). A simple example illustrates best how it works:

function testGenerator() {
    yield 1;
    yield 2;
    yield 3;
}

function runTest() {
    var iter = testGenerator();
    console.log(iter.next()); // outputs 1
    console.log(iter.next()); // outputs 2
    console.log(iter.next()); // outputs 3
    console.log(iter.next()); // throws StopIteration
}

Using yield you can easily create functions that have no end, because only the data you request is generated. For instance, one can create a simple fibionacci-generator like this:

function fib() {
    var a = 1, b = 0;
    while(true) {
        yield a;
        b = a + b;
        yield b;
        a = a + b;
    }
}

For..Of-Loops

The for..of-loop only works on iterators or objects that have the same signature. Use for..of to loop though all the values generated from a generator. For instance, if you take the function runTest created in the previous section, you could rewrite the code to this using for..of:

function runTest() {
    for(var n of testGenerator())
        console.log(n);
}

break and continue works as one would expect, so to print all the fib-numbers less than 100 you could do this:

function printFib() {
    for(var n of fib()) {
        if(n < 100) break;
        console.log(n);
    }
}

Shorthand Function-Syntax

The shorthand function-syntax is fairly straight forward. The valid forms are as follow (all of these are expressions):

1. <identifier> => <expression>
2. <identifier> => <statement>
3. (<arguments>) => <expression>
4. (<arguments>) => <statement>

<arguments> is a comma-separated array of 0 or more identifiers. If any of the variants that ends in an expression is used, said expression is automatically transformed into a returnstatement. This allow for simple map-functions to be written a lot shorter than in regular JavaScript. Here are some samples:

var add = (a, b) => a + b;
function makeFunction(itm) {
    return () => itm;
}
load(data => {
    // do stuff with data
});
About these ads

11 thoughts on “Introducing Augmented JavaScript

    • I know that ofcause. And I had no intention of making Augmented JavaScript ES6 compliant. “await” was the original feature I started with, and was the primary goal. The generators are also different in syntax from ES6.

    • As noted, my goal was never to be ES6-compliant. Also, I loathe the function* syntax, and will not adopt it unless I’m given a compelling enough reason to do so. If ES6-compliance is what you want, there are other preprocessors out there, I’m simply implementing features I like and would like to use (and take my main inspiration from C# which is my second most used language).

  1. Nice!
    Indeed, I always found lame that coffeescript doesn’t read javascript. It should be a requirement when creating a metalanguage: then new people can have fun writing this :

    var f = (a,b) ->
    return a+b

    or this

    var f = function(a,b) {
    a + b
    }

    Makes it especially easy when one want to upgrade a project written in JS to the metalanguage (here coffee script).

    • Personally I like javascript. And not so much CoffeeScript (though I’ve nearly never used the later). I just think it could use some asynchronity-features to get rid of the callback-spagetti (hence await), and yield is allways awesome (though not so much used).

      • I tried Coffeescript but came back to JS since I was always switching between one and another when using open-source libraries.
        And that’s the thing. If javascript C metalanguage (in terms of math inclusion), then it’s powerful otherwise, it is condamned to a specific use with many compatibility issues.

        And your augemented javascript actually includes javascript, which is a good idea I think!

      • A new post is probably coming shortly on some of the updates I’ve made, and new features I’ve added. Also with some explanation as to how js-generators (await/yield) works. As it turns out, await/yield are functionally equivalent on the lower level. Only difference being that an async function does not allow yielded values (await x) to be returned to the caller, and rather schedules continuation until a “real” return is hit.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s