AlexNisnevich / ECMAchine

Lisp-based in-browser toy operating system
http://alex.nisnevich.com/ecmachine/
201 stars 14 forks source link

cons not a cons? #4

Closed davep closed 12 years ago

davep commented 12 years ago

I'm not sure if this is a deliberate design choice or not. I couldn't see anything obvious in the docs so I thought I'd mention it here just in case.

In Scheme you'd expect this:

> (cons 1 2)
(1 . 2)
> (cdr (cons 1 2))
2

But with ECMAchine it works a bit different:

ecmachine:/ guest$ (cons 1 2)
(1 2)
ecmachine:/ guest$ (cdr (cons 1 2))
(2)
AlexNisnevich commented 12 years ago

This is more a product of sloppiness on my part than a deliberate design choice: I didn't want to make a pair data structure, and because I use cons only for combining an element and a list, I thought I could get away with making cons always produce a list. I guess I couldn't.

This shouldn't be too hard to fix: I should do something like

function cons(a, b) {
    if (isAtom(a) && isAtom(b)) {
        return new Pair(a, b);
    }
        // current behavior of cons
    }
}

where Pair inherits from Array but has a different toString and is treated differently by cdr.

AlexNisnevich commented 12 years ago

Ok, I had to refactor some code, but I think pairs work correctly now:

ecmachine:/ guest$ (length '(1 . 2))
2
ecmachine:/ guest$ (length '(1 2))
2
ecmachine:/ guest$ (cons 1 2)
(1 . 2)
ecmachine:/ guest$ (car (cons 1 2))
1
ecmachine:/ guest$ (cdr (cons 1 2))
2
ecmachine:/ guest$ (length (cons 1 2))
2
ecmachine:/ guest$ '(1 . 2)
(1 . 2)
ecmachine:/ guest$ (cdr '(1 . 2))
2
ecmachine:/ guest$ (cdr '(1 2))
(2)
davep commented 12 years ago

Looks good and seems to check out fine here. The only difference I've noticed (comparing to R5RS in DrRacket) is this:

> (cons (cons 1 2) (cons 3 4))
((1 . 2) 3 . 4)

vs:

ecmachine:/ guest$ (cons (cons 1 2) (cons 3 4))
((1 . 2) . (3 . 4))

but that's a printer difference rather than a problem with pairs. If I remember my Lisp/scheme well enough it's still correct. R5RS agrees:

> `((1 . 2) . (3 . 4))
((1 . 2) 3 . 4)
AlexNisnevich commented 12 years ago

Ok. I think I'll probably keep it this way for now, because it would be confusing for me to try to follow the R5RS convention on this and it doesn't seem to really make a difference one way or the other.