Return Styles: Pseud0ch, Terminal, Valhalla, NES, Geocities, Blue Moon. Entire thread

Lisp is fun!

Name: Alexander Dubček 2015-03-24 6:14

I wrote a toy Lisp interpreter this weekend. Programming is pretty much a video game!

https://bitbucket.org/dhoskin/thp

(LET ((f (LAMBDA (x) (IF (x (f (CDR x))) recursion!))))
(f (QUOTE (a b c d e))))

→ args: ((a b c d e))
→ args: ((b c d e))
→ args: ((c d e))
→ args: ((d e))
→ args: ((e))
→ args: (nil)
→ recursion!

Name: Alexander Dubček 2015-03-25 7:40

I'm playing with lexical scope now!

(LET (
(factory (LAMBDA (x) (LAMBDA (y) (CONS x y))))
(helloer (factory hello)))
(helloer world))
→ (hello . world)


It works, but I'm not sure if it's a sane approach.

I only had to add 15 lines of code. When a (LAMBDA (args) ...) is evaled, it is translated into a (CLOSURE (env) (args) ...), where env is the variable list maintained by the interpreter.

This is nice and simple, but on each function call I have to splice the closure's environment onto the outside environment, which is expensive. Recursion won't work without the splice, since the variable pointing to the function isn't in scope at the time of definition.

In practice, this means that the name of the function for recursion is determined dynamically. What do real Lisps do here?

Here's an example of the problem:
(LET (
(f (LAMBDA (l) (IF (l (f (CDR l))) sameF)))
(g f)
(f (LAMBDA (x) (CAR x))))
(g (QUOTE (a b c))))
→ b

i.e., when f calls f recursively, the new definition takes over.

Obviously, the solution is to use a Y combinator.

>>4

Thanks, glad you liked it!

views: 232

I didn't even know there were that many people on /prog/.

Paging through your copy reminded me that there's all sorts of dead cruft I need to remove.

Newer Posts
Don't change these.
Name: Email:
Entire Thread Thread List