Skip to content

Instantly share code, notes, and snippets.

@kenbellows
Last active September 28, 2017 13:10
Show Gist options
  • Save kenbellows/4bdd2070622b1c7367ebb27b78c83950 to your computer and use it in GitHub Desktop.
Save kenbellows/4bdd2070622b1c7367ebb27b78c83950 to your computer and use it in GitHub Desktop.
A JavaScript implementation of Boolean logic in the Lambda calculus
/**
* Implementing Boolean Logic in the Lambda Calculus: A JavaScript Demo
*
* (Inspiration: https://youtu.be/eis11j_iGMs)
*
* It turns out that it's entirely possible in the lambda calculus to define
* the Boolean values TRUE and FALSE in functional terms as lambdas, which
* is pretty cool.
*
* Once you've done that, it's also possible to define the Boolean operators as
* functions that take the Boolean lambdas and apply them to themselves, which
* is also pretty cool.
*
* This is a quick demo of that. Below you will find lambda definitions for
* TRUE and FALSE, as well as the standard Boolean operators NOT, AND, OR,
* XOR, NAND, and NOR. Below the definitions is some code to print out truth
* tables for these values to demonstrate that they work.
*
* It's lambda calculus + Boolean logic + ES6 arrow functions! What more could
* you ask?!
*/
// Define the lambdas
const
// Booleans
TRUE = (a,b) => a,
FALSE = (a,b) => b,
// Logical operators
NOT = (b) => b(FALSE, TRUE),
AND = (a,b) => a(b(TRUE, FALSE), FALSE),
OR = (a,b) => a(TRUE, b(TRUE, FALSE)),
XOR = (a,b) => a(NOT(b), b),
NAND = (a,b) => NOT(AND(a,b)),
NOR = (a,b) => NOT(OR(a, b))
;
/* logging utilities */
// pad a string to five chars (because FALSE, the longest lambda, is 5 chars); set leftPad to true for prefix-padding instead of suffix-padding
const pad5 = (s, leftPad) => s.length >= 5 ? s : (leftPad ? '':s) + (Array(6-s.length).join(' ')) + (leftPad ? s:'');
// given a lambda, return a formatted string for logging
const p = (l,leftPad) => pad5(l.name,leftPad)
/* Generate some truth tables */
// generate the truth table for NOT separately, since it's the only unary operator
console.log(' Input | NOT');
console.log('-------|-------');
console.log(' TRUE |', p(NOT(TRUE)));
console.log(' FALSE |', p(NOT(FALSE)));
console.log('\n');
// list of the binary operators, for looping convenience
let BINARY_OPS = [AND,OR,XOR,NAND,NOR];
// generate the header row
let headers = ' Inputs | '+BINARY_OPS.map(op=>p(op)).join(' | ');
console.log(headers);
console.log('-----------------|'+BINARY_OPS.map(()=> Array(7).join('-')).join('|'));
// loop over the four input cases, generating a truth table row for each one
[[ TRUE, TRUE ],
[ TRUE, FALSE ],
[ FALSE, TRUE ],
[ FALSE, FALSE ]].forEach(([a,b]) => {
console.log(
'( %s, %s )',p(a,true),p(b),'|',
BINARY_OPS.map(op => p(op(a,b))).join(' | ')
);
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment