[refactor] Change the internal representation for is-a-list

This update locks us into a late ECMA-5 implementation (no ECMA-3 for
you!) but it improves the way this representation works and is presented
to users.  It also corresponds (unsurprisingly) to the format used by
my experimental LiSP implementation, thus making my life easier.

Also: Included unit tests to ensure that nilp, listp, pairp, and cellp
all detect the correct matrix of... things.
This commit is contained in:
Elf M. Sternberg 2015-07-22 19:43:59 -07:00
parent 8e89a1fca2
commit 416ad7ac20
2 changed files with 30 additions and 6 deletions

View File

@ -1,6 +1,6 @@
vectorp = (a) -> toString.call(a) == '[object Array]'
cellp = (a) -> vectorp(a) and a.__list == true
cellp = (a) -> vectorp(a) and a.__type == 'list'
pairp = (a) -> cellp(a) and (a.length == 2)
@ -10,12 +10,19 @@ recordp = (a) -> Object.prototype.toString.call(a) == '[object Object]'
nilp = (a) -> cellp(a) and a.length == 0
nil = (-> l = []; l.__list = true; l)()
makeAsCell = (l) ->
Object.defineProperty l, '__type',
value: 'list'
configurable: false
enumerable: false
writable: false
l
nil = (-> makeAsCell([]))()
cons = (a, b = nil) ->
l = if (not (a?)) then b else [a, b]
l.__list = true
l
return nil if (nilp a) and (nilp b)
makeAsCell if (not (a?)) then b else [a, b]
car = (a) -> a[0]
@ -57,6 +64,7 @@ module.exports =
cdr: cdr
list: list
nilp: nilp
cellp: cellp
pairp: pairp
listp: listp
vectorToList: vectorToList

View File

@ -3,6 +3,7 @@ chai.should()
expect = chai.expect
{listToVector, vectorToList, cons, list, nil,
cellp, pairp, listp, nilp,
metacadr, car, cdr, cadr} = require '../src/lists'
describe "Basic list building", ->
@ -27,6 +28,20 @@ describe "Basic list traversing", ->
it "should car cdr cdr", ->
expect(car cdr cdr mcsimple).to.equal("c")
describe "Basic list typing", ->
it "Should recognize an empty cell", ->
expect(cellp(cons())).to.equal(true)
it "Should recognize a nil cell", ->
expect(nilp(cons())).to.equal(true)
it "Should recognize a paired cell", ->
expect(cellp(cons("a", "b"))).to.equal(true)
expect(pairp(cons("a", "b"))).to.equal(true)
expect(listp(cons("a", "b"))).to.equal(false)
it "Should recognize a list", ->
expect(cellp(cons("a"))).to.equal(true)
expect(pairp(cons("a"))).to.equal(true)
expect(listp(cons("a", cons("b")))).to.equal(true)
describe 'Round trip equivalence', ->
for [t, v] in [
[[], []]
@ -40,9 +55,10 @@ describe 'Round trip equivalence', ->
describe 'List Building', ->
for [t, v] in [
[cons(), []]
[cons(nil), [nil]]
[cons(nil), []]
[cons('a'), ['a']]
[cons('a', cons('b')), ['a', 'b']]
[cons('a', cons('b', cons(nil))), ['a', 'b']]
[cons('a', cons('b', cons('c'))), ['a', 'b', 'c']]
[cons('a', cons('b', cons('c'), nil)), ['a', 'b', 'c']]]
do (t, v) ->