-
-
Save rwaldron/826328 to your computer and use it in GitHub Desktop.
| <script src="cons.js"></script> |
| //cons, car and cdr | |
| (function( global ) { | |
| var Cons = { | |
| cons: function() { | |
| var ret = [], | |
| args = [].slice.call( arguments, 0 ), | |
| len = args.length, | |
| idx, arg; | |
| for ( idx = 0; idx < len; idx++ ) { | |
| var arg = args[ idx ]; | |
| ret = ret.concat( arg ); | |
| } | |
| return ret; | |
| }, | |
| // These need to be broken out and abstracted for DRYer code | |
| car: function() { | |
| var car = this.cons.apply( null, [].slice.call( arguments, 0 ) ); | |
| return car.splice( 0, 1 ); | |
| }, | |
| cdr: function() { | |
| var cdr = this.cons.apply( null, [].slice.call( arguments, 0 ) ); | |
| return cdr.splice( 1, cdr.length ); | |
| } | |
| }; | |
| global.cons = Cons.cons; | |
| global.car = Cons.car; | |
| global.cdr = Cons.cdr; | |
| })( this ); | |
| //console.log( | |
| // Actual, | |
| // Expected | |
| //); | |
| console.log( | |
| "cons", | |
| cons( [ "foo", "bar", "baz", "qux" ] ), | |
| [ "foo", "bar", "baz", "qux" ] | |
| ); | |
| console.log( | |
| "cons", | |
| cons( [ "foo", "bar", "baz", "qux" ] , [ "alpha", "beta" ] ), | |
| [ "foo", "bar", "baz", "qux", "alpha", "beta" ] | |
| ); | |
| console.log( | |
| "cons", | |
| cons( ["foo"], cons( ["bar", "baz", "qux"], cons( ["alpha"] ), cons(["beta"]) ) ), | |
| [ "foo", "bar", "baz", "qux", "alpha", "beta" ] | |
| ); | |
| console.log( | |
| "car", | |
| car( [ "foo", "bar", "baz", "qux" ] ), | |
| [ "foo" ] | |
| ); | |
| console.log( | |
| "cdr", | |
| cdr( [ "foo", "bar", "baz", "qux" ] ), | |
| [ "bar", "baz", "qux" ] | |
| ); | |
| console.log( | |
| "car(cdr())", | |
| car( cdr( [ "foo", "bar", "baz", "qux" ] ) ), | |
| [ "bar" ] | |
| ); | |
| // Composites | |
| function cadr( x ) { | |
| return car( cdr( x ) ); | |
| } | |
| console.log( | |
| "cadr", | |
| cadr( [ "foo", "bar", "baz", "qux" ] ), | |
| [ "bar" ] | |
| ); | |
| function caar( x ) { | |
| return car( car( x ) ); | |
| } | |
| console.log( | |
| "caar", | |
| caar( [ "foo", "bar", "baz", "qux" ] ), | |
| [ "foo" ] | |
| ); |
car(cons(X, Y)) == X
cdr(cons(X, Y)) == Y
If X is a string, then car returns a string. if X is a cons, then car needs to return a cons. Likewise with cdr and Y.
cowboy: if s were a list, then you are almost correct. list( cons( "foo", "bar" ), cons( "alpha", "beta" ) ) would return [ [ "foo", "bar" ], [ ["alpha", "beta" ], undefined ] ]. A list is made of conses, but not all conses make proper lists.
var l = list( cons( "foo", "bar" ), cons( "alpha", "beta" ) );
console.log( "list", l, [ [ "foo", "bar" ], [ ["alpha", "beta" ], undefined ] ] );
console.log( "car", car( l ), [ "foo", "bar" ] );
console.log( "cdr", cdr( l ), [ [ "alpha", "beta" ] ] );
console.log( "caar", caar( l ), "foo" );
console.log( "cadr", cadr( l ), [ "alpha", "beta" ] );
console.log( "caar", cdar( l ), "bar" );
console.log( "cadr", cddr( l ), undefined );
Of course, you need a working cons before you can even think of writing list. :)
Gotcha. I was unaware of the distinction between conses and lists, I did some research, and it makes sense now. Thanks! So, what about this, note how I changed the "cdr" test. Is this correct?
var l = list( cons( "foo", "bar" ), cons( "alpha", "beta" ) );
console.log( "list", l, [ [ "foo", "bar" ], [ ["alpha", "beta" ], undefined ] ] );
console.log( "car", car( l ), [ "foo", "bar" ] );
console.log( "cdr", cdr( l ), [ [ "alpha", "beta" ], undefined ] );
console.log( "caar", caar( l ), "foo" );
console.log( "cadr", cadr( l ), [ "alpha", "beta" ] );
console.log( "cdar", cdar( l ), "bar" );
console.log( "cddr", cddr( l ), undefined );
cowboy: yes, good catch. Lisp of course hides the nil at the end of every list, but it is still there
db48x, wouldn't the unit tests be as-follows?
var s = cons( cons( "foo", "bar" ), cons( "alpha", "beta" ) );
console.log( "cons", s, [ [ "foo", "bar" ], ["alpha", "beta" ] ] );
console.log( "car", car( s ), [ "foo", "bar" ] );
console.log( "cdr", cdr( s ), [ [ "alpha", "beta" ] ] );
console.log( "caar", caar( s ), "foo" );
console.log( "cadr", cadr( s ), [ "alpha", "beta" ] );
console.log( "caar", cdar( s ), [ "bar" ] );
console.log( "cadr", cddr( s ), [ "beta" ] );