Kal
Kal is a highly readable, easy-to-use language that compiles to JavaScript. It's designed to be asynchronous and can run both on node.js and in the browser. Kal makes asynchronous programming easy and clean by allowing functions to pause and wait for I/O, replacing an awkward callback syntax with a clean, simple syntax.
Kal is also expressive and offers many useful synonyms and constructs to make code readable in almost plain English.
Try it in your browser.
Kal is designed with a unique philosophy:
- Eliminate the yucky parts of JavaScript, but keep the good stuff including the compatibility, and the great server and client runtime support.
- Make code as readable as possible and make writing code straightforward. Eliminate the urge (and the need) to be terse and complicated.
- Provide an alternative to callbacks (which look weird) and promises (which are weird) while providing excellent, easy-to-use asynchronous support.
Check out the examples for some sample use cases. Check out the project's Github page for more syntax examples.
Links
Asynchronous Wait
The wait for
directive allows a function to pause asynchronously, then resume when a task is complete. For example, the following JavaScript:
function getUserFriends(userName, next) {
db.users.findOne({name:userName}, function (err, user) {
if (err != null) return next(err);
db.friends.find({userId:user.id}, function (err, friends) {
if (err != null) return next(err);
return next(null, friends);
});
});
}
would be equivalent to this in Kal:
task getUserFriends (userName)
wait for user from db.users.findOne {name:userName}
wait for friends from db.friends.find {userId:user.id}
return friends
This includes error handling via callbacks. Consider a more complicated example:
async = require('async');
var getUserFriends = function (userName, next) {
db.users.findOne({name:userName}, function (err, user) {
if (err != null) return next(err);
getFriendsById(user.id, function (err, friends) {
if (err != null) return next(err);
if (user.type == 'power user') {
async.map(friends, getFriendsById, function (err, friendsOfFriends) {
for (var i = 0; i < friendsOfFriends.length; i++) {
for (var j = 0; j < friendsOfFriends[i].length; j++) {
if (friends.indexOf(friendsOfFriends[i][j]) != -1) {
friends.push(friendsOfFriends[i][j]);
}
}
}
return next(null, friends);
});
} else {
return next(null, friends);
}
});
});
}
var getFriendsById = function (userId, next) {
db.friends.find({userId:userId}, function (err, friends) {
if (err != null) return next(err);
return next(null, friends);
});
}
Even using async, it's a lot. Here's the equivalent Kal:
task getUserFriends(userName)
wait for user from db.users.findOne {name:userName}
wait for friends from db.friends.find {userId:user.id}
if user.type is 'power user'
for parallel friend in friends
wait for friendsOfFriend from db.friends.find {userId:friend}
for newFriend in friendsOfFriend
friends.push newFriend unless newFriend in friends
return friends
There are no additional libraries required and everything's a lot more ... vertical. Notice that the wait for
statement works in loops, if
statements, try
/catch
blocks, and all nested permutations. It's completely JavaScript compatible - getUserFriends
would be called the same way and call back with the same results.
Installation Using npm
This is the preferred method for installing Kal. Make sure you have installed node.js. Kal works with versions 0.6, 0.8, and 0.10. It might work with other versions as well. Install the latest "stable" release of Kal using npm:
sudo npm install -g kal
sudo
may not be required depending on how you installed node
.
Syntax Highlighting
A TextMate bundle for TextMate and Sublime Text is available with limited but very useful support for Kal's syntax.