fix conflict with CL’s count function (GitLab issue #1)
Section 2.3 of the Iterate Manual, “Gathering Clauses,” states
These clauses all begin with a verb. When the verb does not conflict with an existing Common Lisp function, then it may be used in either its infinitival or present-participle form (e.g. sum, summing). However, when there is a conflict with Common Lisp, only the present-participle form may be used (e.g. unioning). This is to prevent iterate clauses from clashing with Common Lisp functions.
Unfortunately iterate currently uses the infinitival form of count, which is a Common Lisp function. For example,
(iter (for string in '("foo!" "bar!!" "baz?" "ba!zoo!")) (when (> (count #\! string) 1) (collect string)))
("bar!!" "ba!zoo!"), but instead signals an error
Iterate, in (COUNT ! STRING): Missing value for STRING keyword [Condition of type SIMPLE-ERROR]
According to its documentation, and to be consistent with other cases such as
union, Iterate should use only
It is clear from the text of iterate.lisp that as originally written count correctly was not a synonym for counting, and only at some subsequent point was the buggy behavior introduced: in all the other cognate cases the
defsynonym comes after the corresponding
defclause, while it comes before for
counting/count; in all the other cognate cases the
defclause defines the infinitive form, with the present-participle being the target of the
defsynonym, yet it is the other way around for
count is not exported from the iterate package, as all other infinitive form used by iterate are.
Besides the simple (one line deletion) fix for this bug, I've also updated the unit tests:
- I've add a new unit test,
count.1, that will fail if this bug is at some point inadvertently re-introduced.
- One of the unit tests amusingly contained a work around for this bug; I've backed out that work around.
- Several of the unit tests used the infitival form; I have corrected them.
Prior to making this fix, running the unit tests resulted in five failures, all documented in iterate-tests.lisp. After making this fix no other tests fail.
I've only run the unit tests in SBCL, as I haven't been able to figure out how to get the test framework iterate uses to run elsewhere. However, I have informally confirmed that the fixed version does appear to behave fine in both CCL and CLISP.