[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:
parent
8e89a1fca2
commit
416ad7ac20
|
@ -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
|
||||
|
|
|
@ -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) ->
|
||||
|
|
Loading…
Reference in New Issue