A Function-oriented Dialect of JavaScript
// this script alters a global called "module"
export module
// 'with' imports libraries
with (require 'fs') as fs
[readFile, writeFile]
with (Math)
[ sqrt
, pow
]
// Assign to *local* variables with '='
one = 1
two = 'two'
// call a function by listing its arguments
console.log one two
// unless it has no arguments
bigTwo = two.toUpperCase()
// functions return the value of the last statement evaluated
diagonal = \a b ->
cSquared = a*a + b*b
sqrt cSquared
// this script alters a global called "module"
var readFile,writeFile,fs,sqrt,pow,one,two,bigTwo,diagonal,msg,steps,takeAStep,exp,e3,concatFiles;
// 'with' imports libraries
fs = require('fs');
readFile = owner.readFile; writeFile = owner.writeFile;
(function() { var owner = Math;
sqrt = owner.sqrt;
pow = owner.pow;
})();
// Assign to *local* variables with '='
one = 1;
two = 'two';
// call a function by listing its arguments
console.log(one, two);
// unless it has no arguments
bigTwo = two.toUpperCase();
// functions return the value of the last statement evaluated
diagonal = function (a, b) {
var cSquared = a * a + b * b;
return sqrt(cSquared); };
// if, switch, and try statements can be assigned as values
msg =
if 5 < 6
'impossible'
else if sqrt 2 == 1.4
'I told you it was rational!'
else
'Nothing to see here'
// var can be used to declare scope without setting a value
var steps
// Use := to update values in outer scope
steps = 0
takeAStep = \ ->
console.log 'Taking another step...'
steps := steps + 1
// including variables external to the script
module.exports := { exp: exp, fsConcat: concatFiles }
// Curry functions with @
exp = pow Math.E @
e3 = exp 3
// Use <- to clean up "continuation-passing" code,
// such as often occurs in event-based programming
concatFiles = \a b destination ->
textA <- readFile a
textB <- readFile b
writeFile destination # textA + textB
// if, switch, and try statements can be assigned as values
if (5 < 6) {
msg = 'impossible';
} else if (sqrt(2) === 1.4) {
msg = 'I told you it was rational!';
} else {
msg = 'Nothing to see here'; };
// var can be used to declare scope without setting a value
var steps;
// Use := to update values in outer scope
steps = 0;
takeAStep = function () {
console.log('Taking another step...');
steps = steps + 1; };
// including variables external to the script
module.exports = { exp: exp, fsConcat: concatFiles };
// Curry functions with @
exp = function (_p0) { return pow(Math.E, _p0); };
e3 = exp(3);
// Use <- to clean up "continuation-passing" code,
// such as often occurs in event-based programming
concatFiles = function (a, b, destination) {
return readFile(a, function (textA) {
return readFile(b, function (textB) {
return writeFile(destination, (textA + textB)); }); }); };
A block is interpreted either a continuation of the preceding, line, or as many separate lines, according to two rules:
for
or if
statement, will be a set of separate lines.In other words, if the line we're indenting from wants to end in
a brace {
in JavaScript, it will be. Otherwise it won't.
if
statements require indented blocks for each branch.
The if-case
construct can be more concise:
// A concise form for if-else-if statements
hour = new Date() .getHours()
message = if case
hour < 4 -> 'Night owl'
hour < 6 -> 'Up early'
hour < 12 -> 'Good morning'
default -> 'Hello'
// A concise form for if-else-if statements
hour = new Date().getHours();
if (hour < 4) { message = 'Night owl';
} else if (hour < 6) { message = 'Up early';
} else if (hour < 12) { message = 'Good morning';
} else { message = 'Hello'; };
For loops have two special forms: for own
and for index
.
// hasOwnProperty() check
x = { name: 'Bond', fullname: 'James Bond' }
for own k in x
console.log (k + ':') x[k]
// can read value with key
for own k:v in x
console.log v
// for use with arrays
nums = [1, 2, 3]
for index i in nums
console.log nums[i]
for index i:n in nums
console.log n
// hasOwnProperty() check
x = { name: 'Bond', fullname: 'James Bond' };
for (k in (_o1 = x)) { if (_o1.hasOwnProperty(k)) {
console.log((k + ':'), x[k]); }}
// can read value with key
for (k in (_o2 = x)) { if (_o2.hasOwnProperty(k)) { v = _o2[k];
console.log(v); }}
// for use with arrays
nums = [1, 2, 3];
for (_o3 = nums, i = 0, _len1 = _o3.length; i < _len1; i ++) {
console.log(nums[i]); }
for (_o4 = nums, i = 0, _len2 = _o4.length; i < _len2; i ++) { n = _o4[i];
console.log(n); }
Since assignments don't return a value, things like
while (row = getRow())
will not work in Papuscript. Do this
instead:
while row = getRow(), row
process row
while(row = getRow(), row) {
process(row); }
In switch
statements, cases do not fall through. To match
multiple values to the same block, list them separated by commas.
switch x
case 1
alert 'min'
case 6
alert 'max'
case 2, 3, 4, 5
alert 'middle'
default
throw new Error 'invalid roll'
switch (x) {
case 1:
alert('min'); break;
case 6:
alert('max'); break;
case 2: case 3: case 4: case 5:
alert('middle'); break;
default:
throw new Error('invalid roll');}
/* You can /* NEST */ comments */
// == becomes ===
bool = 1 == '1'
// undefined becomes "void 0"
nil = undefined
// one-liner
add = \a b -> a + b
// syntactic sugar for 'diagonalSafe = \a b ->'
diagonalSafe a b =
if a <= 0 || b <= 0
console.log 'Not a real rectangle!'
return 0 // explicit return
diagonal a b
// Ternary operator is different
// It's more readable with a symbol at the beginning
min = ?? a < b : a : b
/* You can NEST comments */
// == becomes ===
bool = 1 === '1';
// undefined becomes "void 0"
nil = void 0;
// one-liner
add = function (a, b) { return a + b; };
// syntactic sugar for 'diagonalSafe = \a b ->'
diagonalSafe = function diagonalSafe(a, b) {
if (a <= 0 || b <= 0) {
console.log('Not a real rectangle!');
return 0; } // explicit return
return diagonal(a, b); };
// Ternary operator is different
// It's more readable with a symbol at the beginning
min = a < b ? a : b;
// To chain methods without lots of parentheses
// put a space before the dot
str = myString.replace '\\' '\\\\' .replace '"' '\\"'
// # encloses rest of line in ()
console.log # diagonal 3 4
// You can use a function like an operator by surrounding it in backticks
eleven = 5 `add` 6
// numeric indices can be referenced like named members, with a dot
first = \ ->
console.log arguments.0
// Symbol string: an alphanumeric name preceded by a colon
// useful when a string is semantic (such as the name of a method)
assignIfEmpty member value obj =
if undefined == obj[member]
obj[member] := value
assignIfEmpty :name 'MyModule' module
// A list of strings can be written thus:
colors = %{ red blue green }
// To chain methods without lots of parentheses
// put a space before the dot
str = myString.replace('\\', '\\\\').replace('"', '\\"');
// # encloses rest of line in ()
console.log(diagonal(3, 4));
// You can use a function like an operator by surrounding it in backticks
eleven = add(5, 6);
// numeric indices can be referenced like named members, with a dot
first = function () {
return console.log(arguments[0]); };
// Symbol string: an alphanumeric name preceded by a colon
// useful when a string is semantic (such as the name of a method)
assignIfEmpty = function assignIfEmpty(member, value, obj) {
if (void 0 === obj[member]) {
obj[member] = value; }};
assignIfEmpty("name", 'MyModule', module);
// A list of strings can be written thus:
colors = ['red', 'blue', 'green'];
Project maintained by Rob Rosenbaum Theme by mattgraham, modified by Rob Rosenbaum