diff --git a/src/lambda-calculus.js b/src/lambda-calculus.js index 401ff30..807c26d 100644 --- a/src/lambda-calculus.js +++ b/src/lambda-calculus.js @@ -340,7 +340,7 @@ function evalLC(term) { // callback function which will evaluate term.body in an env with the input function result(arg) { let argEnv; - if ( arg.term && arg.env ) ({ term: arg, env: argEnv } = arg); // if callback is passed another callback, or a term + if ( arg?.term && arg?.env ) ({ term: arg, env: argEnv } = arg); // if callback is passed another callback, or a term const termVal = new Tuple( typeof arg !== 'number' ? arg : fromInt(arg) , new Env(argEnv) ); return runEval( new Tuple(term.body, new Env(env).setThunk(term.name, termVal)), stack ); } diff --git a/tests/scott-lists/test.js b/tests/scott-lists/test.js index 18bc911..4090fa0 100644 --- a/tests/scott-lists/test.js +++ b/tests/scott-lists/test.js @@ -21,7 +21,7 @@ const {"take-while":takeWhile,"drop-while":dropWhile,"drop-while-end":dropWhileE const {"split-at":splitAt,get,set} = solution; const {any,all,find,"find-indices":findIndices,"find-index":findIndex} = solution; const {partition,span,"minimum-by":minimumBy,"maximum-by":maximumBy} = solution; -const {"insret-by":insertBy,"sort-by":sortBy,reverse} = solution; +const {"insert-by":insertBy,"sort-by":sortBy,reverse} = solution; const {"zip-with":zipWith,zip,unzip} = solution; const {"group-by":groupBy,"nub-by":nubBy,"delete-by":deleteBy,"delete-firsts-by":deleteFirstsBy} = solution; const {init,last,tails,inits,slice,transpose} = solution; @@ -31,13 +31,14 @@ const fromInt = LC.fromIntWith(LC.config); const toInt = LC.toIntWith(LC.config); const fromArray = xs => xs.reduceRight( (z,x) => cons(x)(z) , nil ) ; const toArray = foldl ( z => x => [...z,x] ) ([]) ; +const fromPair = ([fst,snd]) => Pair(fst)(snd) ; +const toPair = xy => xy ( fst => snd => [fst,snd] ) ; +const toNullable = fn => optX => optX (null) (fn) ; const rnd = (m,n=0) => Math.random() * (n-m) + m | 0 ; const elements = xs => xs[ rnd(xs.length) ] ; const rndArray = size => Array.from( { length: rnd(size) }, () => rnd(size) ) ; -const refReplicate = length => x => Array.from( { length }, () => x ) ; - describe("Scott Lists",function(){ it("nil,cons,singleton",()=>{ assert.deepEqual( toArray( nil ), [] ); @@ -56,4 +57,27 @@ describe("Scott Lists",function(){ assert.deepEqual( toArray( scanl (add) (zero) (fromArray(xs.map(fromInt))) ).map(toInt), xs.reduce( (z,x) => [ ...z, z[z.length-1]+x ] , [0] ), `after ${ i } tests` ); } }); + it("take,drop",()=>{ + for ( let i=1; i<=10; i++ ) { + const n = rnd(i), xs = rndArray(i); + assert.deepEqual( toArray( take (fromInt(n)) (fromArray(xs.map(fromInt))) ).map(toInt), xs.slice(0,n), `after ${ i } tests` ); + assert.deepEqual( toArray( drop (fromInt(n)) (fromArray(xs.map(fromInt))) ).map(toInt), xs.slice(n), `after ${ i } tests` ); + } + }); + it("append,concat,snoc",()=>{ + for ( let i=1; i<=10; i++ ) { + const x = rnd(i), xs = rndArray(i), ys = rndArray(i); + assert.deepEqual( toArray( append (fromArray(xs.map(fromInt))) (fromArray(ys.map(fromInt))) ).map(toInt), [...xs,...ys], `after ${ i } tests` ); + assert.deepEqual( toArray( concat (fromArray([ fromArray(xs.map(fromInt)), fromArray(ys.map(fromInt)) ])) ).map(toInt), [...xs,...ys], `after ${ i } tests` ); + assert.deepEqual( toArray( snoc (fromArray(xs.map(fromInt))) (fromInt(x)) ).map(toInt), [...xs,x], `after ${ i } tests` ); + } + }); + it("uncons",()=>{ + for ( let i=1; i<=10; i++ ) { + const xs = rndArray(i); + assert.deepEqual( toNullable ( xy => toPair(xy).map( (x,i) => i ? toArray(x).map(toInt) : toInt(x) ) ) ( uncons (fromArray(xs.map(fromInt))) ), + xs.length ? [ xs[0], xs.slice(1) ] : null , + `after ${ i } tests` ); + } + }); });