9. Examples
This example is for a Reverse Polish Notation (RPN) calculator. The Squiggle version contains more exception throwing, which is automatically generated by Squiggle.
If you're not familiar with RPN, here's a quick translation:
RPN: 2 3 4 * 3 - +
Normal: 2 + ((3 * 4) - 3)
rpn.js
var text = "2 3 4 * 3 - +";
function tokenize(text) {
return text.split(" ").map(tokenValue);
}
var table = {
"+": function(a, b) { return a + b; },
"-": function(a, b) { return a - b; },
"*": function(a, b) { return a * b; },
"/": function(a, b) { return a / b; }
};
function tokenValue(token) {
if (table.hasOwnProperty(token)) {
return table[token];
} else {
return Number(token);
}
}
function evaluate_(stack, values) {
if (values.length === 0) {
return stack[0];
}
var i = stack.length;
var x = values[0];
var v = values.slice(1);
if (typeof x === "function") {
var a = stack[i - 1];
var b = stack[i - 2];
var y = x(a, b);
var newStack = stack.slice(0, i - 2).concat([y]);
} else {
var newStack = stack.concat([x]);
}
return evaluate_(newStack, v);
}
function evaluate(text) {
return evaluate_([], tokenize(text));
}
console.log(evaluate(text));
rpn.squiggle
let {Number, console} = global
let text = "2 3 4 * 3 - +"
def tokenize(text) do
text.split(" ").map(fn(x, ...) tokenValue(x))
end
def tokenValue(token) do
match token
case "+" then ["Func", fn(a, b) a + b]
case "-" then ["Func", fn(a, b) a - b]
case "*" then ["Func", fn(a, b) a * b]
case "/" then ["Func", fn(a, b) a / b]
case num then ["Num", Number(num)]
end
end
def evaluate_(stack, values) do
match [stack, values]
case [[first, second, ...rest], [["Func", f], ...xs]] then
evaluate_([f(first, second)] ++ rest, xs)
case [stack, [["Num", n], ...xs]] then
evaluate_([n] ++ stack, xs)
case [[value, ...], _] then
value
end
end
def evaluate(text) do
evaluate_([], tokenize(text))
end
console.log(evaluate(text))