Budden,
Like I said, I think we have passed the level of "break someone's (reasonable) code" and is more in the realm of "a matter of taste". It is true that iterate exports many symbols and I believe that I have a vague memory that this was an annoyance long ago, so it might be a hurdle for new users. You in effect have convinced me that it won't be detrimental to me or any hypothetical user I can think of (other than those people that are doing a (defclause :for ...) and they deserve what they get). If the description I gave of the new functionality is accurate, the only issues I still have are:
1. This will discourage new users/developers from writing their own extensions to Iterate, as they will think there is something special about the symbols :FOR, :WHILE, :WITH, etc (and they are special, in that the user cannot write their own just like them).
2. It will make the extensions that are written a little odd looking as they don't keep with the general interface of the abstraction.
3. Given 1 and 2, someone might wonder in the future why there isn't a way to define your own keyword style iterate construct. If this happens we are in the odd position where there are two nearly independent methods of extension in Iterate (both of which is, of course, in addition to the clause overloading that you can do by using DEFCLAUSE with other "keyword specialization" (like the in-whole-vector example in the manual)). As I discussed, one of these methods of extending Iterate is inherently weaker than the other due to name collisions introduced by you. This seems like a real mess to be avoided.
These are all social problems, however, not technical. Iterate is something I very much enjoy using and would dislike it if, due to these social problems, extensibility is either weakened, turning Iterate into merely Loop with parentheses, or bifurcated such that extending Iterate is a mess (but a working mess). Of the two, I can deal with messy, inconsistent code.
On the idea of backwards compatibility, I would say your change is basically backward compatible and don't worry about *FEATURES*. I would suggest you provide a new package ITERATE-KEYWORDS that only exports ITER and ITERATE but keep the ITERATE package exports the same. Just my opinion and I think this is what you already intend to do.
As to the matter of taste, you argue that this is annoying to use the Iterate package as other packages define and export the symbols FOR or WHILE. This is true across all of Common Lisp and we have ways of dealing with it (i.e. shadowing, giving the full package qualified name). It is certainly annoying when it comes up, but I think you wouldn't argue that we should remedy package collisions by interning one package's exported symbols to some other unrelated package (say the keyword package) and modify the Lisp eval function to map those references to the correct package. Other than the fact that with Iterate we have the means to modify the Lisp eval function portably and safely (a macro environment) I'm not sure I see how this is very different. So, I'm not sure this is "the right thing to do," but I am also sympathetic to the fact that symbol name collisions can be irritating when you want to use multiple packages.
In case it is not entirely clear, I am not the Iterate maintainer, nor a developer on the Iterate project at all. I am just writing this as a party with a vested interest. The silence of the maintainer is a bit troublesome, though.
Zach
On Tue, Oct 16, 2012 at 12:15 PM, Denis Budyak budden73@gmail.com wrote:
Zach, list,
Why isn't your patch nothing more than a single file that looks like: (iterate:defsynonym :for iterate:for) (iterate:defsynonym :collect iterate:collect) ... (iterate:defsynonym :appending iterate:appending) Why isn't this just a small separate library called iterate-keyword that only exports ITERATE?
This is because synonym mechanism is not universal. It doesn't cover cases of iterate:first-time-p, iterate:next-iteration etc. defsynonym simply do not work for them. To make them work, one need to patch iterate itself.
One last thing, I would hope that you wouldn't actually attempt to patch iterate to not export FOR, WHILE
Of course I didn't attempt this. In fact, there is no need to use iterate in any package, if one can use keywords. Just writing (:import-from :iter #:iter) would suffice.
Is the root of your desire to do this the fact that you want to use the symbols FOR, WHILE, COLLECT, etc in the same package that you want to use Iterate?
Iterate is a very agressive exporter of symbols :) When I started using iterate, I just tried to :use both :iterate and :cl-utilities and this gave me a conflict. One can easily imagine an applicaion (e.g. language parser) where symbols like FOR and WHILE are treated as data and it is desirable for them to come from specific package, not from iterate.
Some other person is likely to implement simplified "while" loop. Third person might just try playing with iterate, and she will get conflict in the following innocent lisp session:
; Hallo from your lisp %(in-package :cl-user) %(use-package :iterate) ... conflict ... as FOR might be exported into :cl-user from loop during initialization.
but it would also break any body's code that decided to (defmacro-clause :for ...)
Yes, and it is expected, but sometimes breaking changes occur in a software.
(defun :go ...)
defsynonym is not a defun, it only puts a property on a symbol, so the symbol does not change its meaning outside of iterate construct.
Just because I agree one should not normally (defun :for), I believe that change proposed is not very harmful as it can be hardly expected that it would break anyone's code.
If it is considered a serious threat, we could define *features* member so that iterate could be bulid either with or without keywords support. Unfortunately it seem to be impossible to enable keywords support via a separate library.
Regards, Budden