|I just watched the "Clojure for Lisp Programmers" talk and was impressed by the conj function and the generic sequence interface to lists, maps and vectors.|
In Arc, the function map is accepts both hashtables and lists, but those are hardcoded. If we overload car and cdr, we can treat other things (like lazy lists) as lists:
but then the whole my-lazy-list would be forced evaluated. How can we ensure that map does not only accept lazy lists, but also return lazy lists?
(map my-function my-lasy-list)
With dynamic bindings we could change the behaviour of map, so it returns a lazy list:
but dynamic variables are considered harmful and hard to reason about.
(dyn-let cons lazy-cons
(map my-function my-lazy-list))
To avoid dynamic binding at all costs, I propose a reification of closures, the with-closure function. It takes a function and
some bindings and returns the function with the added bindings.
Because map is a recursive function, the modified version should call the modified version, and not the global map, so it gets a bit more complicated:
((with-closure (let x nil (fn () x)) 'x t))
(with-closure map 'cons lazy-cons)
This could be wrapped in a macro:
(let lazy-map map
(with-closure lazy-map 'cons lazy-cons)
(with-closure lazy-map 'map lazy-map)))
This would allow us to write a lazy-list modifier that makes a function operate on lazy lists, or more generally to retrofit abstractions onto previously defined functions.
(mac rwith-closure (fun . mappings)
`(let ,newfun (with-closure ,fun ,@mappings)
(= ,newfun (with-closure ,newfun ',fun ,newfun)))))