-
Notifications
You must be signed in to change notification settings - Fork 6
Home
I believe less is more. It is the first principle of design and foundation of just about every good programming practice: DRY, KISS, ZEN (YAGNI), single responsibility principle, interface segregation, etc... That's why I wrote CaffeineScript. This infographic shows the result:
CaffeineScript, with the help of ArtSuite, takes 3x less code to write the complete implementation of Tic-Tac-Toe. In general, CaffeineScript is 2.5-3 times more efficient than JSX, TypeScript or JavaScript. Imagine seeing 3x as much code on screen at once. Imagine having 3x less code to write. Imagine having 3x less code to change when you need to refactor. Imagine having 3x less code to debug.
TicTacToe source:
TicTacToe live:
Of course, just because CaffeineScript can reduce code-size by 3x doesn't mean you'll be a full 3x faster. CaffeineScript cannot reduce the essential logic of your code. However, it dramatically cuts back the written noise, so you can see your core logic clearly.
Read more about programming with less:
JavaScript has a golden heart. At its core, it is a powerful hybrid of object-oriented, functional and dynamically-typed languages. Combined with modern runtimes, world-class garbage collectors and JIT compilers, JavaScript can be a surprisingly good platform for building great applications.
However, JavaScript has an ailing body. Even now, in 2018, JavaScript has major syntax and semantic problems which make it error prone and dangerous. JavaScript's syntax is excessively verbose. Code readability matters, especially for large projects, and JavaScript's syntax is the least readable of any major language. This is easy to fix, and the rewards can be huge.
Further, JavaScript has many dangerous holes in its semantics which can introduce subtle, hard to find bugs. They include accidental globals, weakly-typed truth, weakly-typed equality and other weakly-typed operators. Thankfully, the core JavaScript semantics are good, and these auxiliary semantics can be partially or fully fixed without changing JavaScript.
CaffeineScript's goal is to maximize productivity for JavaScript-based projects. It does this primarily by minimizing syntax and patching the holes in JavaScript's semantics.
I love CoffeeScript. I love the visual blocking of bracket-less blocks. As I used it over the years, though, I started noting it wasn't very consistent. I was frustrated by all-to-frequent edge cases, where I had to revert to using brackets. For example, all array literals still require brackets ([]) in CoffeeScript. Eventually I couldn't stand it anymore. I set out to write a language that could parse bracketless blocks consistently.
If you love CoffeeScript, or even if you liked some parts but others drove you crazy, I've got an awesome language for you.
CaffeineScript is an open-source programming language that compiles to JavaScript. The goal is to minimize total effort, over a product's lifetime, for the entire team. Design thinking is essential for achieving that goal. That means user-experience and graphic design are as important as computer-science and software engineering. A well-designed language makes code more beautiful, programming more fun, and, ultimately, lets us get more done with less effort.
CaffeineScript starts where CoffeeScripts left off, fixing its shortcomings and taking a big step forward for high-productivity javascript. Two concrete examples: improved React-style programming and 90% reduced module-specific code. The result is a lean, high-level language that empowers you to get the most out of JavaScript.
CaffeineScript:
JavaScript:
"use strict";
let Caf = require("caffeine-script-runtime");
Caf.defMod(module, () => {
return Caf.importInvoke(
["FluxComponent", "Element"],
[global, require("art-suite")],
(FluxComponent, Element) => {
let PlayerList;
return (PlayerList = Caf.defClass(
class PlayerList extends FluxComponent {},
function(PlayerList, classSuper, instanceSuper) {
this.subscriptions("players.currentPlayers");
this.prototype.render = function() {
return Element(
{ childrenLayout: "column" },
Caf.each(
this.currentPlayers.sort((a, b) => {
return b.score - a.score;
}),
[],
(player, cafK, cafInto) => {
cafInto.push(
require("./PlayerLine")(player, { key: player.name })
);
}
)
);
};
}
));
}
);
});
Related: ArtSuite
A brief, interactive slideshow written in CaffeineScript
CaffeineScript is working and usable. The semantics and syntax may shift slightly as I work through the remaining bugs.
npm install caffeine-script
- CaffeineScript Documentation Wiki
- Get Started
- Benefits
- Highlights
- Productivity by Design
- CaffeineScript Design
- What is CaffeineScript Good For?
- Why CaffeineScript over CoffeeScript?
- Why CaffeineScript over JavaScript?
- Discuss on Google Groups
- Request, Suggest or Report Bugs on Github Issues
- View source or Fork on Github
# CaffeineScript - 27 tokens and 0 must-match-tokens
import &ArtSuite
class Login extends Component
render: ->
Element
TextElement
text: :username
size: ww: 1, hch: 1
TextInput
placeholder: "" enter username here
size: ww: 1, hch: 1
// JavaScript - 73 tokens including 28 must-match-tokens
let {
Component,
Element,
TextElement,
TextInput
} = require('art-suite');
module.exports = class Login extends Component {
render() {
return Element(
TextElement({
text: 'username',
size: {ww: 1, hch: 1}
}),
TextInput({
placeholder: 'enter username here',
size: {ww: 1, hch: 1}
})
);
};
};
# CaffeineScript - 20 tokens
1d: 1 2 3 4 5 6 7 8 9
2d:
1 2 3
4 5 6
7 8 9
// JavaScript - 54 tokens
{
"1d": [1, 2, 3, 4, 5, 6, 7, 8, 9],
"2d": [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
};
# CaffeineScript - 18 tokens - 0 must-match-tokens
users =
id: 123 username: :shanebdavis born: 1976 fullName: "" Shane Brinkman-Davis Delamore
id: 456 username: :alanturing born: 1912 fullName: "" Alan Turing
// JavaScript - 35 tokens - 14 must-match tokens
let users = [
{id: 123, username: "shanebdavis", born: 1976, "Shane Brinkman-Davis Delamore"},
{id: 456, username: "alanturing", born: 1912, "Alan Turing"}
];
# CaffeineScript - 15 tokens - 0 must-match-tokens
nameToColor:
red: #f00
green: #0f0
colorToName:
#f00: :red
#0f0: :green
style:
fontSize: 12pt
padding: 25px
// JavaScript - 40 tokens - 24 must-match-tokens
{
nameToColor: { red: "#f00", green: "#0f0" },
colorToName: { "#f00": "red", "#0f0": "green" },
style: { fontSize: "12pt", padding: "25px" }
};
# CaffeineScript 15 tokens - 2 must-match tokens
fontProps = object value, key from allProps when /^font/.test key
// JavaScript 44 tokens - 16 must-match tokens
var fontProps = {}, key, value;
for (key in allProps) {
value = allProps[key];
if (/^font/.test(key)) {
fontProps[key] = value;
}
}
Is there interest in TypeScript support? If so, with some help, I could add it. CaffeineScript could easily support a modified TypeScript syntax for type annotation and integration into the TypeScript universe.
More on CaffeineScript and Static Typing
I owe a debt of gratitude to Jeremy Ashkenas and the CoffeeScript community. It is my primary inspiration, and what the CaffeineScript compiler was originally written in. More on inspirations from CoffeeScript: Coming from CoffeeScript.
- Home
- Get Started
- Benefits
- Highlights
- Productivity by Design
- CaffeineScript Design
- What is CaffeineScript Good For?
- Get the most out of JavaScript
- Language Comparison
- CHANGELOG
- Blocks Instead of Brackets
- Binary Line-Starts
- Everything Returns a Value
- Streamlined Modules
- Scopes and Variables
- Optional Commas
- Semantics
- Ambiguities