Changed the list structure to not respect cons(nil, nil) == nil.
I think this is a mistake, but at the moment I'm not clever enough to figure out how to properly acknowledge an end-of-list without a special sentinel, which I'm trying to avoid. TODO: Revisit this. Modified Makefile to produce JUnit-compatible error messages. Style (coffee-lint cleanup)
This commit is contained in:
parent
46f6600a55
commit
54da8c6b65
|
@ -16,4 +16,5 @@ bin/escodegen
|
|||
bin/esgenerate
|
||||
bin/mocha
|
||||
*.js
|
||||
test-reports.xml
|
||||
|
||||
|
|
6
Makefile
6
Makefile
|
@ -18,7 +18,11 @@ node_modules: package.json
|
|||
mkdir -p node_modules
|
||||
npm install
|
||||
|
||||
test: node_modules
|
||||
test: clean node_modules
|
||||
@JUNIT_REPORT_PATH=test-reports.xml JUNIT_REPORT_STACK=1 ./node_modules/.bin/mocha \
|
||||
--reporter mocha-jenkins-reporter --compilers coffee:coffee-script/register || true
|
||||
|
||||
ltest: node_modules
|
||||
@node_modules/.bin/mocha --compilers coffee:coffee-script/register
|
||||
|
||||
clean:
|
||||
|
|
|
@ -13,7 +13,7 @@ nilp = (a) -> cellp(a) and a.length == 0
|
|||
nil = (-> l = []; l.__list = true; l)()
|
||||
|
||||
cons = (a, b = nil) ->
|
||||
l = if not (a?) then [] else if (nilp a) then b else [a, b]
|
||||
l = if (not (a?)) then b else [a, b]
|
||||
l.__list = true
|
||||
l
|
||||
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
{car, cdr, cons, listp, pairp, nilp, nil, list, listToString} = require './lists'
|
||||
{car, cdr, cons, listp, pairp, nilp,
|
||||
nil, list, listToString} = require './lists'
|
||||
|
||||
reduce = (lst, iteratee, memo, context) ->
|
||||
count = 0
|
||||
console.log lst
|
||||
return memo if nilp lst
|
||||
memo = iteratee.call(context, memo, (car lst), count)
|
||||
lst = cdr lst
|
||||
|
@ -13,43 +15,28 @@ reduce = (lst, iteratee, memo, context) ->
|
|||
null
|
||||
memo
|
||||
|
||||
map = (lst, iteratee, context) ->
|
||||
|
||||
map = (lst, iteratee, context, count = 0) ->
|
||||
return nil if nilp lst
|
||||
root = cons()
|
||||
product = iteratee.call(context, (car lst), count, lst)
|
||||
rest = if (nilp cdr lst) then nil else
|
||||
map((cdr lst), iteratee, context, count + 1)
|
||||
cons product, rest
|
||||
|
||||
reducer = (memo, item, count) ->
|
||||
next = cons(iteratee.call(context, item, count, lst))
|
||||
memo[1] = next
|
||||
next
|
||||
|
||||
reduce(lst, reducer, root, context)
|
||||
(cdr root)
|
||||
|
||||
rmap = (lst, iteratee, context) ->
|
||||
rmap = (lst, iteratee, context, count = 0) ->
|
||||
return nil if nilp lst
|
||||
root = cons()
|
||||
|
||||
reducer = (memo, item, count) ->
|
||||
cons(iteratee.call(context, item, count, lst), memo)
|
||||
|
||||
reduce(lst, reducer, root, context)
|
||||
product = (if (nilp cdr lst) then nil else
|
||||
map((cdr lst), iteratee, context, count + 1))
|
||||
cons product, iteratee.call(context, (car lst), count, lst)
|
||||
|
||||
filter = (lst, iteratee, context) ->
|
||||
return nil if nilp lst
|
||||
root = cons()
|
||||
if iteratee.call(context, (car lst), lst)
|
||||
cons (car lst), filter (cdr lst)
|
||||
else
|
||||
filter (cdr list)
|
||||
|
||||
reducer = (memo, item, count) ->
|
||||
if iteratee.call(context, item, count, lst)
|
||||
next = cons(item)
|
||||
memo[1] = next
|
||||
next
|
||||
else
|
||||
memo
|
||||
|
||||
reduce(lst, reducer, root, context)
|
||||
if (pairp root) then (cdr root) else root
|
||||
|
||||
reverse = (lst) -> reduce(lst, ((memo, value) -> cons(value, memo)), cons())
|
||||
reverse = (lst) -> rmap lst, (i) -> i
|
||||
|
||||
module.exports =
|
||||
reduce: reduce
|
||||
|
@ -57,4 +44,4 @@ module.exports =
|
|||
rmap: rmap
|
||||
filter: filter
|
||||
reverse: reverse
|
||||
|
||||
|
||||
|
|
|
@ -1,20 +1,16 @@
|
|||
chai = require 'chai'
|
||||
chai.should()
|
||||
expect = chai.expect
|
||||
expect = chai.expect
|
||||
|
||||
{listToVector, vectorToList, cons, list, nil, metacadr} = require '../src/lists'
|
||||
|
||||
describe "Basic list building", ->
|
||||
for [t, v] in [
|
||||
[cons(), cons()]
|
||||
[cons(nil), cons()]
|
||||
[cons(), cons(nil)]
|
||||
[cons('a'), cons('a')]
|
||||
[cons('a', cons('b', cons('c'))), cons('a', cons('b', cons('c')))]
|
||||
[cons('a', cons('b', cons('c'))), cons('a', cons('b', cons('c', nil)))]
|
||||
[cons('a', cons('b', cons('c', nil))), cons('a', cons('b', cons('c')))]
|
||||
[cons(nil, cons('a')), cons('a')] # Test for identity; consing nil to anything results in anything
|
||||
[cons(nil, cons(nil, cons(nil))), nil]]
|
||||
[cons('a', cons('b', cons('c', nil))), cons('a', cons('b', cons('c')))]]
|
||||
do (t, v) ->
|
||||
it "should match #{t}", ->
|
||||
expect(t).to.deep.equal(v)
|
||||
|
@ -28,20 +24,20 @@ describe 'Round trip equivalence', ->
|
|||
do (t, v) ->
|
||||
it "should successfully round-trip #{t}", ->
|
||||
expect(listToVector vectorToList t).to.deep.equal(v)
|
||||
|
||||
|
||||
describe 'List Building', ->
|
||||
for [t, v] in [
|
||||
[cons(), []]
|
||||
[cons(nil), []]
|
||||
[cons(nil), [nil]]
|
||||
[cons('a'), ['a']]
|
||||
[cons('a', cons('b')), ['a', 'b']]
|
||||
[cons('a', cons('b', cons('c'))), ['a', 'b', 'c']]
|
||||
[cons('a', cons('b', cons('c'), nil)), ['a', 'b', 'c']]]
|
||||
do (t, v) ->
|
||||
it "should cons a list into #{v}", ->
|
||||
expect(listToVector t).to.deep.equal(v)
|
||||
expect(listToVector t).to.deep.equal(v)
|
||||
|
||||
describe 'Dynamic list constructor', ->
|
||||
describe 'Dynamic list constructor', ->
|
||||
for [t, v] in [
|
||||
[list(), []]
|
||||
[list('a'), ['a']]
|
||||
|
@ -53,7 +49,7 @@ describe 'Dynamic list constructor', ->
|
|||
|
||||
mcsimple = cons('a', cons('b', cons('c')))
|
||||
|
||||
describe 'Metacadr Simple', ->
|
||||
describe 'Metacadr Simple', ->
|
||||
for [t, v, r] in [
|
||||
['car', 'a']
|
||||
['cadr', 'b']
|
||||
|
@ -62,9 +58,13 @@ describe 'Metacadr Simple', ->
|
|||
it "The #{t} should read #{v}", ->
|
||||
expect(metacadr(t)(mcsimple)).to.equal(v)
|
||||
|
||||
mccomplex = vectorToList([['a', 'b', 'c'], ['1', '2', '3'], ['X', 'Y', 'Z'], ['f', 'g', 'h']])
|
||||
mccomplex = vectorToList([
|
||||
['a', 'b', 'c'],
|
||||
['1', '2', '3'],
|
||||
['X', 'Y', 'Z'],
|
||||
['f', 'g', 'h']])
|
||||
|
||||
describe 'Metacadr Complex', ->
|
||||
describe 'Metacadr Complex', ->
|
||||
for [t, v, r] in [
|
||||
['cadar', 'b']
|
||||
['caadddr', 'f']
|
||||
|
|
|
@ -1,12 +1,13 @@
|
|||
chai = require 'chai'
|
||||
chai.should()
|
||||
expect = chai.expect
|
||||
expect = chai.expect
|
||||
|
||||
{listToVector, vectorToList, listToString, cons, list, nil} = require '../src/lists'
|
||||
{listToVector, vectorToList,
|
||||
listToString, cons, list, nil} = require '../src/lists'
|
||||
{map, reduce, filter, reverse} = require '../src/reduce'
|
||||
|
||||
id = (item) -> item
|
||||
|
||||
|
||||
describe 'Map Identity Testing', ->
|
||||
|
||||
samples = [
|
||||
|
@ -16,12 +17,12 @@ describe 'Map Identity Testing', ->
|
|||
cons('a', cons('b'))
|
||||
cons('a', cons('b', cons('c'))),
|
||||
cons('a', cons('b', cons('c'), nil))]
|
||||
|
||||
|
||||
for t in samples
|
||||
do (t) ->
|
||||
it "should produce the same thing as #{t}", ->
|
||||
product = map(t, id)
|
||||
expect(product).to.deep.equal(t)
|
||||
expect(product).to.deep.equal(t)
|
||||
|
||||
describe 'Filter Testing Testing', ->
|
||||
|
||||
|
@ -33,12 +34,12 @@ describe 'Filter Testing Testing', ->
|
|||
[vectorToList([1, 2, 3 ,4]), cons(2, cons(4))]]
|
||||
|
||||
truth = (item) -> item % 2 == 0
|
||||
|
||||
|
||||
for [t, v] in samples
|
||||
do (t, v) ->
|
||||
it "should produce the same thing as #{v}", ->
|
||||
product = filter(t, truth)
|
||||
expect(product).to.deep.equal(v)
|
||||
expect(product).to.deep.equal(v)
|
||||
|
||||
describe 'Reverse', ->
|
||||
|
||||
|
|
Loading…
Reference in New Issue