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:
Elf M. Sternberg 2015-06-22 17:03:21 -07:00
parent 46f6600a55
commit 54da8c6b65
6 changed files with 47 additions and 54 deletions

1
.gitignore vendored
View File

@ -16,4 +16,5 @@ bin/escodegen
bin/esgenerate
bin/mocha
*.js
test-reports.xml

View File

@ -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:

View File

@ -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

View File

@ -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

View File

@ -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']

View File

@ -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', ->