Cleanup Issue WITH-PACKAGE-ITERATOR-END

Category
CLARIFICATION
Related issues
HASH-TABLE-PACKAGE-GENERATORS

Problem Description

The writeup in HASH-TABLE-PACKAGE-GENERATORS:ADD-WITH-WRAPPER is unfortunately ambiguous about whether it's valid to call the next-function again after it has returned NIL once. The descriptions of WITH-HASH-TABLE-ITERATOR and WITH-PACKAGE-ITERATOR say:

After all entries (symbols) have been returned [by successive invocations of (<next-fn>)], then only one value is returned, namely NIL.

The problem is that if calling the next-function again after it returns NIL is valid, it turns out that the implementation of the generator has to be less efficient. But these language features exist primarily for LOOP and other portable iteration facilities, and LOOP (and probably the other facilities too) will never call the next-function after it returns NIL, because that terminates the iteration.

This is Symbolics issue #24.

Proposal (ONCE-ONLY)

Clarify that the consequences are undefined if the next-function is called after it has returned NIL as its first value.

Test Cases

Macroexpand the following:

    (loop for k being each hash-key of ht do (print k))

    (loop for s being each symbol of 'common-lisp do (print s))

    (with-hash-table-iterator (next ht)
       (print (next)))

    (with-package-iterator (next 'common-lisp :internal :external)
       (print (next)))

Rationale

It seems silly to have needless generality in these macros, when the next-function is already specified to have dynamic extent anyway. The genmerality just causes a performance problem.

Current Practice

Symbolics Genera 8.0 uses the less efficient implementation that supports reinvoking the next-function after it returns NIL.

Lucid 4.0.0 Beta-1 does not support WITH-PACKAGE-ITERATOR and WITH-HASH-TABLE-ITERATOR, but has a similar internal facility.

In both of the above implementations, LOOP generates code that does not call the next-function again after it returns NIL.

Other implementations were not surveyed.

Cost to Implementors

None.

Cost to Users

None.

Cost of Non-Adoption

Small performance degradation.

Performance Impact

Small performance improvement.

Benefits

Small performance improvement.

Aesthetics

Not applicable to these macros.

Discussion

None.

Edit History