Nondestructive setf? - functional-programming

Common Lisp seems to go to great lengths to provide both nondestructive functions (like subst & remove) and destructive functions and modify macros (like delete & rotatef) for general use. Presumably this is to effectively support both functional and nonfunctional styles of programming. But there also seems to be a particular bias toward the nonfunctional style in the design of the ubiquitous setf. The setf macro, incorporating generalized reference, is apparently flexible enough to modify any specifiable place (except perhaps for immutable integers and characters). This power probably accounts for its widespread useage in spite of its nonfunctional/destructive behavior.
The question is why there is not a corresponding "functional style" nondestructive operator, patterned after setf (call it put, since set is already taken), analogous to other nondestructive/destructive lisp operator pairs. Such an operator would probably take the same arguments, a place and a value, but would return a copy of the object in which the place was embedded, instead of the new value at that place. It also would probably involve a universal copier of some sort, with the standard setf simply modifying the copy before returning it. The nondestructive operator then could be used in lieu of setf for most assignments, with setf being reserved for really large objects. Is such an operator feasible (or even possible) given the (presumed) requirement for a universal copier and the need to recover an object from an arbitrary place embedded in it?

Common Lisp has no universal copier for the same reason it does not have a built-in printable representation of CLOS objects (see, e.g., Saving CLOS objects): the power of MOP.
Specifically, object creation can have arbitrary side effects whose replication is hard to guarantee. E.g., define initialize-instance for your class to modify slots based something fluid (e.g., tides or just random). Then the result of make-instance called with the same arguments twice may be different. You might argue that this is an argument in favor of a memcpy-style generic copier. However, imagine now a class which does instance accounting (an :allocation :class slot which contains a hash table mapping unique ID to instance). Now, the round trip from the copied object via the table will get a different object (the original, not the copy) - a major contract violation. And these examples are just the tip of the iceberg.
However, I would not agree that Common Lisp encourages imperative style more than functional style. It merely discourages the style you describe (copy+setf). Think about it this way: from the functional POV, a copy is indistinguishable from the original (because everything is immutable).
There are also "small hints" showing a clear preference for functional style.
Observe that the "natural" names
(e.g., append) are reserved
for non-destructive functions; the destructive versions
(e.g., nconc) are given
obscure names.
Additionally, pathnames, characters and numbers (including composites like ratio and complex) are
immutable, i.e., all pathname and number functions create new objects (functional style).
Thus, IMO, Common Lisp encourages programmers to use functional style while still making imperative style feasible, in conformance to the slogan "simple things should be easy, hard things should be possible".
See also Kent Pitman's writeup.

There is no universal setter either, but with SETF you are supposed to provide one when you use DEFINE-SETF-EXPANDER. I suppose you could define the equivalent of lenses/functional references. For another approach, Clojure defines an update function (borrowed from other languages, I know it exists in Prolog), which is not universal either. The FSET library provides some functional structures, notably associative maps which work like the ones in Clojure.
Suppose for a moment you limit yourself to structures:
(defstruct foo a b c)
(defstruct bar x y z)
(defparameter *test*
(make-foo :a (make-bar :x 0 :y 0 :z 0)
:b 100
:c "string"))
;; *test* is now
;; #S(FOO :A #S(BAR :X 0 :Y 0 :Z 0) :B 100 :C "string")
The following approach makes a copy, it relies on copy-structure and slot-value, which, while not standard, is well supported:
(defun update (structure keys value)
(if (endp keys)
value
(destructuring-bind (key &rest keys) keys
(let ((copy (copy-structure structure)))
(setf (slot-value copy key)
(update (slot-value copy key)
keys
value))
copy))))
You can update *test* as follows:
(update *test* '(a z) 10)
Here is a trace:
0: (UPDATE #S(FOO :A #S(BAR :X 0 :Y 0 :Z 0) :B 100 :C "string") (A Z) 10)
1: (UPDATE #S(BAR :X 0 :Y 0 :Z 0) (Z) 10)
2: (UPDATE 0 NIL 10)
2: UPDATE returned 10
1: UPDATE returned #S(BAR :X 0 :Y 0 :Z 10)
0: UPDATE returned #S(FOO :A #S(BAR :X 0 :Y 0 :Z 10) :B 100 :C "string")
In order to generalize, you could accept a function instead of a value, so that you could implement the equivalent of incf by partially applying the update function with #'1+ (the resulting closure would accept a list of keys).
Also, you need to generalize the copy operation, which is possible with generic functions. Likewise, you could use other kinds of accessors, and replace slot-value with a generic access function (for which there is a (setf access) operation). This generic copy/setf approach could be wasteful, however, if you want to share some data. For example, you only need to copy the part of a list which leads to your data, not the cons cells that are following it.
You could define some facility for defining custom updaters:
(defmethod perform-update (new (list list) position)
(nconc (subseq list 0 position)
(list new)
(nthcdr (1+ position) list)))

Related

Specification of conses

The Wikipedia-page about car and cdr says that a cons is a pair of pointers.
The following code seems to confirm that:
(progn
(setq a '(1 . 2))
(setq b a)
(setf (car b) 10)
(print a))
The evaluation of that form gives the cons (10 . 2). Setting the car of b changes the car of a. You can try that in the online repl at compileonline.com.
Where is that behavior defined in the Common Lisp specification?
(I've read some of the text but couldn't find the section pin-pointing that behavior.)
Interestingly the Wikipedia page on conses says "cons constructs memory objects which hold two values or pointers to values". If the atom 1 would directly be stored in the cons object then changing b wouldn't change a, would it?
I assume above that a and b hold the cons objects and not pointer to conses.
Even if the actual lisp implementation works with pointers this should not be visible on repl-level or should it according to the spec? One could achieve a similar effect when one assumes that a and b hold pointers that both point to the same cons.
Consing, i.e., the construction of lists through repeated application of cons, supports the assumption that conses are represented by pointers in symbol values.
The following two forms are equivalent:
(let ((a '(1)))
(setq b (cons 2 a)))
(setq b '(2 1))
Setting the car of b changes the car of a.
You are not setting the car of b. You are setting the car of the same cons cell which is referenced by b and a.
CL-USER 1 > (let (a b)
(setq a (cons 1 2))
(setq b a)
(eq a b))
T
Explanation:
we have variables a and b.
(cons 1 2) returns a cons cell
(setq a (cons 1 2)) sets a to the result of (cons 1 2), a cons cell.
(setq b a) evaluates a, which returns above cons cell and sets b to that cons cell.
The key to understand is that evaluation of variables and functions returns non-primitive (that is other than primitive numbers, characters, ...) objects as themselves - not as a copy.
I assume above that a and b hold the cons objects and not pointer to conses.
That's wrong. a and b are variables, which just point to both the same single cons cell.
"cons constructs memory objects which hold two values or pointers to values"
In a Common Lisp implementation something like small numbers (fixnums) might be stored directly in a cons cell. One can not reliably compare numbers by identity (using EQ) and has to do numeric comparison (EQL, =, ...).
OTOH, cons cells can't be stored inside cons cells and thus are referenced by pointers internally.
The operations you use:
SETQ : First form1 is evaluated and the result is stored in the variable var1. -> Notice how it says: result and not copy of the result.
RPLCA - this is what (setf CAR) actually uses. : rplaca replaces the car of the cons with object and The cons is modified -> thus it modifies the cons object it gets passed as an argument.
Evaluation - since you execute your code, the rules for evaluation apply.
Further useful to understand the execution model of Lisp:
An old Lisp book: 'Anatomy of LISP' by John Allen. (amazon)
A Scheme spec like R5RS.
Lisp in small pieces, a book explaining the execution models of Scheme/Lisp and their implementation.
First of all, your code is invalid because you're not allowed to modify constant lists. It should be:
(progn
(setq a (cons 1 2))
(setq b a)
(setf (car b) 10)
(print a))
When you perform an assignment like (setq b a), it sets the value of b to be the same as the value of a. The specification of SETQ says nothing about making a copy of the value, so the two variables contain the same value, which in this case is a cons cell.
Setting the car of that cons cell modifies that object -- again, there's no copying being done. So you'll see the change through any variable that refers to the cons cell, or any other reference (it could be in a structure slot, an array element, another cons cell, etc.).
I don't think the specification ever actually comes out and says that these things are all the same, it's just implicit in the fact that we're passing around abstract objects, and no copying is done unless you call a function that's explicitly defined to do so (e.g. COPY-TREE).
The specification doesn't talk about pointers, but that's generally what's going on under the covers. A cons cell is like a C structure:
typedef struct cons {
lisp_object car,
lisp_object cdr
} cons;
lisp_object would probably be a union of various types (some immediate types for things like FIXNUM, and pointers for other types). When a variable contains a cons, it actually contains a pointer to the above structure, and the assignment copies the pointer, not the structure. So the Lisp code is analogous to C code like:
cons *a = make_cons(1, 2);
cons *b = a;
b->car = 10;
printf("%d\n", a->car);

Common lisp CLOS dispatch

Is there a good way to get a generic function to dispatch on the car of a list?
I've been working on a symbolic algebra program, and at the moment am storing a lot of data as lists with different keywords as the cars to indicate type. For example, I have simplices stored as '(:simplex #(0 1 2)), and I have something I'm calling steps for the time being stored as '(:step #(0 1 0 1)). I would like to be able to take the dimension and boundary of both of these, ideally using some built in dispatch mechanism.
Bit hacky, but you can do this with eql specialisers.
(defmethod foo ((first (eql :simplex)) (thing vector))
<method body here>)
You'd then have to call that as either
(foo :step #(0 1 0 1))
or
(apply #'foo '(:step #(0 1 0 1)))
So, for your situation, you'd do something like
(defmethod dimension ((type (eql :simplex)) (thing vector))
;; calculate dimension of a SIMPLEX here
)
(defmethod dimension ((type (eql :step)) (thing vector))
;; calculate dimension of a STEP here
)
and the same for boundary.
If the things you're processing are really meant to be different structures, you might consider defining structs or classes instead of using raw lists. At that point, you could easily just define methods on the appropriate type, which would let you sidestep the awkward calling requirements of this approach.

What is the difference between eq?, eqv?, equal?, and = in Scheme?

I wonder what the difference is between those operations in Scheme. I have seen similar questions in Stack Overflow but they are about Lisp, and there is not a comparison between three of those operators.
I am writing the different types of commands in Scheme, and I get the following outputs:
(eq? 5 5) -->#t
(eq? 2.5 2.5) -->#f
(equal? 2.5 2.5) --> #t
(= 2.5 2.5) --> #t
Why is this the case?
I'll answer this question incrementally. Let's start with the = equivalence predicate. The = predicate is used to check whether two numbers are equal. If you supply it anything else but a number then it will raise an error:
(= 2 3) => #f
(= 2.5 2.5) => #t
(= '() '()) => error
The eq? predicate is used to check whether its two parameters respresent the same object in memory. For example:
(define x '(2 3))
(define y '(2 3))
(eq? x y) => #f
(define y x)
(eq? x y) => #t
Note however that there's only one empty list '() in memory (actually the empty list doesn't exist in memory, but a pointer to the memory location 0 is considered as the empty list). Hence when comparing empty lists eq? will always return #t (because they represent the same object in memory):
(define x '())
(define y '())
(eq? x y) => #t
Now depending upon the implementation eq? may or may not return #t for primitive values such as numbers, strings, etc. For example:
(eq? 2 2) => depends upon the implementation
(eq? "a" "a") => depends upon the implementation
This is where the eqv? predicate comes into picture. The eqv? is exactly the same as the eq? predicate, except that it will always return #t for same primitive values. For example:
(eqv? 2 2) => #t
(eqv? "a" "a") => depends upon the implementation
Hence eqv? is a superset of eq? and for most cases you should use eqv? instead of eq?.
Finally we come to the equal? predicate. The equal? predicate is exactly the same as the eqv? predicate, except that it can also be used to test whether two lists, vectors, etc. have corresponding elements which satisfy the eqv? predicate. For example:
(define x '(2 3))
(define y '(2 3))
(equal? x y) => #t
(eqv? x y) => #f
In general:
Use the = predicate when you wish to test whether two numbers are equivalent.
Use the eqv? predicate when you wish to test whether two non-numeric values are equivalent.
Use the equal? predicate when you wish to test whether two lists, vectors, etc. are equivalent.
Don't use the eq? predicate unless you know exactly what you're doing.
There are a full two pages in the RnRS specification related to eq?, eqv?, equal? and =. Here is the Draft R7RS Specification. Check it out!
Explanation:
= compares numbers, 2.5 and 2.5 are numerically equal.
equal? for numbers reduces to =, 2.5 and 2.5 are numerically equal.
eq? compares 'pointers'. The number 5, in your Scheme implementation, is implemented as an 'immediate' (likely), thus 5 and 5 are identical. The number 2.5 may require an allocation of a 'floating point record' in your Scheme implementation, the two pointers are not identical.
eq? is #t when it is the same address/object. Normally one could expect #t for same symbol, boolean and object and #f for values that is of different type, with different values, or not the same structure Scheme/Lisp-implementations has a tradition to embed type in their pointers and to embed values in the same space if it's enough space. Thus some pointers really are not addresses but values, like the char R or the Fixnum 10. These will be eq? since the "address" is an embedded type+value. Some implementations also reuse immutable constants. (eq? '(1 2 3) '(1 2 3)) might be #f when interpreted but #t when compiled since it might get the same address. (Like the constant String pool in Java). Because of this, many expresions involving eq? are unspecified, thus wether it evaluates to #t or #f is implementation dependent.
eqv? are #t for the same things as eq?. It is also #t if it's a number or character and it's value is the same, even when the data is too big to fit into a pointer. Thus for those eqv? does the extra work of checking that type is one of the supported, that both are the same type and it's target objects have the same data value.
equal? is #t for the same things as eqv? and if it's a compound type like pair, vector,
string, and bytevector it recursively does equal? with the parts. In practice it will return #t if the two objects looks the same. Prior to R6RS, it's unsafe to use equal? on circular structures.
= is like eqv? but it only works for numeric types. It might be more efficient.
string=? is like equal?, but it only works for strings. It might be more efficient.
equal? recursively compares two objects (of any type) for equality.
Note this could be expensive for a large data structure since potentially the entire list, string, vector, etc must be traversed.
If the object just contains a single element (EG: number, character, etc), this is the same as eqv?.
eqv? tests two objects to determine if both are "normally regarded as the same object".
eqv? and eq? are very similar operations, and the differences between them are going to be somewhat implementation specific.
eq? is the same as eqv? but may be able to discern finer distinctions, and may be implemented more efficiently.
According to the spec, this might be implemented as a fast and efficient pointer comparison, as opposed to a more complicated operation for eqv?.
= compares numbers for numerical equality.
Note that more than two numbers can be provided, eg: (= 1 1.0 1/1 2/2)
You don't mention a scheme implementation, but in Racket, eq? only returns true if the arguments refer to the same object. Your second example is yielding #f because the system is creating a new floating point number for each argument; they're not the same object.
equal? and = are checking for value equivalence, but = is only applicable to numbers.
If you're using Racket, check here for more information. Otherwise, check the documentation of your scheme implementation.
Think of eq? as pointer equality. The authors of the Report want it to be as general as possible so they don't say this outright because it's implementation-dependent, and to say it, would favor the pointer-based implementations. But they do say
It will usually be possible to implement eq? much more efficiently than eqv?, for example, as a simple pointer comparison
Here's what I mean. (eqv? 2 2) is guaranteed to return #t but (eq? 2 2) is unspecified. Now imagine a pointer-based implementation. In it eq? is just pointer comparison. Since (eq? 2 2) is unspecified, it means that this implementation is free to just create new memory object representation of each new number it reads from the source code. eqv? must actually inspect its arguments.
OTOH (eq 'a 'a) is #t. This means that such implementation must recognize symbols with duplicate names and use the same one representation object in memory for all of them.
Suppose an implementation is not pointer-based. As long as it adheres to the Report, it doesn't matter. The authors just don't want to be seen as dictating the specifics of implementations to the implementors, so they choose their wording carefully.
This is my guess anyway.
So very coarsely, eq? is pointer equality, eqv? is (atomic-)values-aware, equal? is also structure-aware (checks into its arguments recursively, so that finally (equal? '(a) '(a)) is required to be #t), = is for numbers, string=? is for strings, and the details are in the Report.
Apart from the previous answers, I will add some comments.
All these predicates want to define the abstract function of identity for an object but in different contextes.
EQ? is implementation-dependent and it does not answer the question are 2 objects the same? only in limited use. From implementation point of view, this predicate just compares 2 numbers (pointer to objects), it does not look at the content of the objects. So, for example, if your implementation does not uniquely keep the strings inside but allocates different memory for each string, then (eq? "a" "a") will be false.
EQV? -- this looks inside the objects, but with limited use. It is implementation-dependent if it returns true for (eqv? (lambda(x) x) (lambda(x) x)). Here it's a full philosophy how to define this predicate, as we know nowadays that there are some fast methods to compare the functionality of some functions, with limited use. But eqv? provides coherent answer for big numbers, strings, etc.
Practically, some of these predicates tries to use the abstract definition of an object (mathematically), while others use the representation of an object (how it's implemented on a real machine). The mathematical definition of identity comes from Leibniz and it says:
X = Y iff for any P, P(X) = P(Y)
X, Y being objects and
P being any property associated with object X and Y.
Ideally it would be to be able to implement this very definition on computer but for reasons of indecidability and/or speed it is not implemented literally. This is why there are lots of operators that try each one to focus on different viewpoints around this definition.
Try to imagine the abstract definition of an identity for a continuation. Even if you can provide a definition of a subset of functions (sigma-recursive class of functions), the language does not impose any predicate to be true or false. It would complicate a lot both the definition of the language and much more the implementation.
The context for the other predicates is easier to analyze.

Why is foldl defined in a strange way in Racket?

In Haskell, like in many other functional languages, the function foldl is defined such that, for example, foldl (-) 0 [1,2,3,4] = -10.
This is OK, because foldl (-) 0 [1, 2,3,4] is, by definition, ((((0 - 1) - 2) - 3) - 4).
But, in Racket, (foldl - 0 '(1 2 3 4)) is 2, because Racket "intelligently" calculates like this: (4 - (3 - (2 - (1 - 0)))), which indeed is 2.
Of course, if we define auxiliary function flip, like this:
(define (flip bin-fn)
(lambda (x y)
(bin-fn y x)))
then we could in Racket achieve the same behavior as in Haskell: instead of (foldl - 0 '(1 2 3 4)) we can write: (foldl (flip -) 0 '(1 2 3 4))
The question is: Why is foldl in racket defined in such an odd (nonstandard and nonintuitive) way, differently than in any other language?
The Haskell definition is not uniform. In Racket, the function to both folds have the same order of inputs, and therefore you can just replace foldl by foldr and get the same result. If you do that with the Haskell version you'd get a different result (usually) — and you can see this in the different types of the two.
(In fact, I think that in order to do a proper comparison you should avoid these toy numeric examples where both of the type variables are integers.)
This has the nice byproduct where you're encouraged to choose either foldl or foldr according to their semantic differences. My guess is that with Haskell's order you're likely to choose according to the operation. You have a good example for this: you've used foldl because you want to subtract each number — and that's such an "obvious" choice that it's easy to overlook the fact that foldl is usually a bad choice in a lazy language.
Another difference is that the Haskell version is more limited than the Racket version in the usual way: it operates on exactly one input list, whereas Racket can accept any number of lists. This makes it more important to have a uniform argument order for the input function).
Finally, it is wrong to assume that Racket diverged from "many other functional languages", since folding is far from a new trick, and Racket has roots that are far older than Haskell (or these other languages). The question could therefore go the other way: why is Haskell's foldl defined in a strange way? (And no, (-) is not a good excuse.)
Historical update:
Since this seems to bother people again and again, I did a little bit of legwork. This is not definitive in any way, just my second-hand guessing. Feel free to edit this if you know more, or even better, email the relevant people and ask. Specifically, I don't know the dates where these decisions were made, so the following list is in rough order.
First there was Lisp, and no mention of "fold"ing of any kind. Instead, Lisp has reduce which is very non-uniform, especially if you consider its type. For example, :from-end is a keyword argument that determines whether it's a left or a right scan and it uses different accumulator functions which means that the accumulator type depends on that keyword. This is in addition to other hacks: usually the first value is taken from the list (unless you specify an :initial-value). Finally, if you don't specify an :initial-value, and the list is empty, it will actually apply the function on zero arguments to get a result.
All of this means that reduce is usually used for what its name suggests: reducing a list of values into a single value, where the two types are usually the same. The conclusion here is that it's serving a kind of a similar purpose to folding, but it's not nearly as useful as the generic list iteration construct that you get with folding. I'm guessing that this means that there's no strong relation between reduce and the later fold operations.
The first relevant language that follows Lisp and has a proper fold is ML. The choice that was made there, as noted in newacct's answer below, was to go with the uniform types version (ie, what Racket uses).
The next reference is Bird & Wadler's ItFP (1988), which uses different types (as in Haskell). However, they note in the appendix that Miranda has the same type (as in Racket).
Miranda later on switched the argument order (ie, moved from the Racket order to the Haskell one). Specifically, that text says:
WARNING - this definition of foldl differs from that in older versions of Miranda. The one here is the same as that in Bird and Wadler (1988). The old definition had the two args of `op' reversed.
Haskell took a lot of stuff from Miranda, including the different types. (But of course I don't know the dates so maybe the Miranda change was due to Haskell.) In any case, it's clear at this point that there was no consensus, hence the reversed question above holds.
OCaml went with the Haskell direction and uses different types
I'm guessing that "How to Design Programs" (aka HtDP) was written at roughly the same period, and they chose the same type. There is, however, no motivation or explanation — and in fact, after that exercise it's simply mentioned as one of the built-in functions.
Racket's implementation of the fold operations was, of course, the "built-ins" that are mentioned here.
Then came SRFI-1, and the choice was to use the same-type version (as Racket). This decision was question by John David Stone, who points at a comment in the SRFI that says
Note: MIT Scheme and Haskell flip F's arg order for their reduce and fold functions.
Olin later addressed this: all he said was:
Good point, but I want consistency between the two functions.
state-value first: srfi-1, SML
state-value last: Haskell
Note in particular his use of state-value, which suggests a view where consistent types are a possibly more important point than operator order.
"differently than in any other language"
As a counter-example, Standard ML (ML is a very old and influential functional language)'s foldl also works this way: http://www.standardml.org/Basis/list.html#SIG:LIST.foldl:VAL
Racket's foldl and foldr (and also SRFI-1's fold and fold-right) have the property that
(foldr cons null lst) = lst
(foldl cons null lst) = (reverse lst)
I speculate the argument order was chosen for that reason.
From the Racket documentation, the description of foldl:
(foldl proc init lst ...+) → any/c
Two points of interest for your question are mentioned:
the input lsts are traversed from left to right
And
foldl processes the lsts in constant space
I'm gonna speculate on how the implementation for that might look like, with a single list for simplicity's sake:
(define (my-foldl proc init lst)
(define (iter lst acc)
(if (null? lst)
acc
(iter (cdr lst) (proc (car lst) acc))))
(iter lst init))
As you can see, the requirements of left-to-right traversal and constant space are met (notice the tail recursion in iter), but the order of the arguments for proc was never specified in the description. Hence, the result of calling the above code would be:
(my-foldl - 0 '(1 2 3 4))
> 2
If we had specified the order of the arguments for proc in this way:
(proc acc (car lst))
Then the result would be:
(my-foldl - 0 '(1 2 3 4))
> -10
My point is, the documentation for foldl doesn't make any assumptions on the evaluation order of the arguments for proc, it only has to guarantee that constant space is used and that the elements in the list are evaluated from left to right.
As a side note, you can get the desired evaluation order for your expression by simply writing this:
(- 0 1 2 3 4)
> -10

Permuting output of a tree of closures

This a conceptual question on how one would implement the following in Lisp (assuming Common Lisp in my case, but any dialect would work). Assume you have a function that creates closures that sequentially iterate over an arbitrary collection (or otherwise return different values) of data and returns nil when exhausted, i.e.
(defun make-counter (up-to)
(let ((cnt 0))
(lambda ()
(if (< cnt up-to)
(incf cnt)
nil))))
CL-USER> (defvar gen (make-counter 3))
GEN
CL-USER> (funcall gen)
1
CL-USER> (funcall gen)
2
CL-USER> (funcall gen)
3
CL-USER> (funcall gen)
NIL
CL-USER> (funcall gen)
NIL
Now, assume you are trying to permute a combinations of one or more of these closures. How would you implement a function that returns a new closure that subsequently creates a permutation of all closures contained within it? i.e.:
(defun permute-closures (counters)
......)
such that the following holds true:
CL-USER> (defvar collection (permute-closures (list
(make-counter 3)
(make-counter 3))))
CL-USER> (funcall collection)
(1 1)
CL-USER> (funcall collection)
(1 2)
CL-USER> (funcall collection)
(1 3)
CL-USER> (funcall collection)
(2 1)
...
and so on.
The way I had it designed originally was to add a 'pause' parameter to the initial counting lambda such that when iterating you can still call it and receive the old cached value if passed ":pause t", in hopes of making the permutation slightly cleaner. Also, while the example above is a simple list of two identical closures, the list can be an arbitrarily-complicated tree (which can be permuted in depth-first order, and the resulting permutation set would have the shape of the tree.).
I had this implemented, but my solution wasn't very clean and am trying to poll how others would approach the problem.
Thanks in advance.
edit Thank you for all the answers. What I ended up doing was adding a 'continue' argument to the generator and flattening my structure by replacing any nested list with a closure that permuted that list. The generators did not advance and always returned the last cached value unless 'continue' was passed. Then I just recursively called each generator until I got to the either the last cdr or a nil. If i got to the last cdr, I just bumped it. If I got to a NIL, I bumped the one before it, and reset every closure following it.
You'll clearly need some way of using each value returned by a generator more than once.
In addition to Rainer Joswig's suggestions, three approaches come to mind.
Caching values
permute-closures could, of course, remember every value returned by each generator by storing it in a list, and reuse that over and over. This approach obviously implies some memory overhead, and it won't work very well if the generated sequences can be infinite.
Creating new generators on each iteration
In this approach, you would change the signature of permute-closures to take as arguments not ready-to-use generators but thunks that create them. Your example would then look like this:
(permute-closures (list (lambda () (make-counter 3))
(lambda () (make-counter 3))))
This way, permute-closures is able to reset a generator by simply recreating it.
Making generator states copyable
You could provide a way of making copies of generators along with their states. This is kind of like approach #2 in that permute-closures would reset the generators as needed except the resetting would be done by reverting to a copy of the original state. Also, you would be able to do partial resets (i.e., backtrack to an arbitrary point rather than just the beginning), which may or may not make the code of permute-closures significantly simpler.
Copying generator states might be a bit easier in a language with first-class continuations (like Scheme), but if all generators follow some predefined structure, abstracting it away with a define-generator macro or some such should be possible in Common Lisp as well.
I would add to the counter either one of these:
being able to reset the counter to the start
letting the counter return NIL when the count is done and then starting from the first value again on the next call

Resources