alandipert / gherkin

a functional programming language and interpreter written in GNU Bash 4
https://tailrecursion.com/~alan/Lisp/GherkinHistory.html
BSD 3-Clause "New" or "Revised" License
522 stars 31 forks source link

closures broken #33

Closed alandipert closed 10 years ago

alandipert commented 11 years ago

Consider the following program, a simple HTML templating system using closures:

(def tag
  (fn (name)
    (fn (& children)
      (str "<" name ">"
           (apply str children)
           "</" name ">"))))

(def head  (tag "head"))
(def title (tag "title"))

(head (title "cool page"))

It returns "<title><title>cool page</title></title>". Notice the tag name duplication.

This happens because head and title are identical functions - both point to the same instance of the cons (fn (& children) ...), and (eq? head title) is t.

Because head and title are identical, they share an entry in the environments array, and whatever lexical context the function is evaluated in last overwrites the environment for all references.

fix ideas, questions

quoll commented 10 years ago

Wondering if it's feasible to redefine what fns are. Instead of a single list of (fn args body...), what if the args were a pair of lists, with symbols in one, and values in the other. Unbound functions have a nil bindings list. Binding the function would require a copy, but it would only be the fn and the container for the args, with the args list and the body being shared between copies.

I don't think it's possible to bind an outer function while leaving inner functions unbound, so I think it would work. It would need some rewriting of the various 'eval' functions.