Cleanup Issue REMF-MULTIPLE

Category
CLARIFICATION/CHANGE
References
REMPROP (p166), REMF (p167)

Problem Description

The descriptions of REMF and REMPROP are not explicit about what happens in the case that a duplicated indicator occurs on the plist. One or both indicators might be removed.

Proposal (REMOVE-ONE)

Clarify that REMF and REMPROP at most one indicator/value pair from the designated plist.

Rationale

In a property list maintained by the normal property list operations, there will only be one property by each name. This approach won't waste time trying to remove other properties which are not present in the first place.

Proposal (REMOVE-ALL)

Clarify that REMF and REMPROP remove all matching indicator/value pairs from the designated plist.

Rationale

In a property list maintained by other operations than the standard ones, this might be useful. Also, since the return value of REMF and REMPROP is not well-defined, iterating to remove more than one property is expensive because you have to start over from the head of the list.

Proposal (IS-AN-ERROR)

Clarify that it "is an error" to pass a list with a duplicated indicator to REMF or any other function that takes a property list (including GETF); it "is an error" for a symbol to have duplicated properties on its property list.

Rationale

	The only thing that CLtL pp 163-167 says about
	duplicated indicators on plists is that there aren't any
	(first line on page 164). It does not even gurantee
 	that GETF returns the first occurrence.

Test Cases

  ;; Case #1 - removing symbol properties,etc. using REMPROP

(DEFUN REMF-MULTIPLE-TEST-1 () (LET ((SYMBOL (GENSYM))) (SETF (SYMBOL-PLIST SYMBOL) (LIST 'A 'B 'C 'D 'A 'B 'C 'D)) (FORMAT T "~&Before: ~S~%" (SYMBOL-PLIST SYMBOL)) (REMPROP SYMBOL 'A) (FORMAT T "~&After: ~S~%" (SYMBOL-PLIST SYMBOL)) (FORMAT T "~&This implementation uses REMF-MULTIPLE:~:[REMOVE-ALL~;REMOVE-ONE~] ~ for REMPROP.~%" (GET SYMBOL 'A))))

  ;; Case #2 - removing keywords,etc. using REMF

(DEFUN REMF-MULTIPLE-TEST-2 () (LABELS ((HELPER (&REST ARGUMENTS &KEY (A 1) (B 2)) (FORMAT T "~&Helper received: ~S~%" ARGUMENTS) (LIST A B)) (DRIVER (&REST ARGUMENTS) (FORMAT T "~&Helper received: ~S~%" ARGUMENTS) (SETQ ARGUMENTS (COPY-LIST ARGUMENTS)) (REMF ARGUMENTS ':A) (APPLY #'HELPER ARGUMENTS))) (LET ((RESULT (DRIVER :A 3 :B 4 :A 5 :B 6))) (FORMAT T "~&Returned: ~S~%" RESULT) (FORMAT T "~&This implementation uses REMF-MULTIPLE:~:[REMOVE-ALL~;REMOVE-ONE~] ~ for REMF.~%" (= (CAR RESULT) 5)))))

Current Practice

Symbolics implements REMF-MULTIPLE:REMOVE-ONE.

Cost to Implementors

For implementations needing to change, the cost of a change is probably very small in most cases. Implementations needing change which do REMPROP and/or REMF in microcode might have a slightly harder time, but any change should still be very localized.

Cost to Users

None. Users must tread lightly on this issue right now because it is not well-defined.

Cost of Non-Adoption

The language description would continue to be vague for no particularly good reason.

Benefits

IS-ERROR at least makes the situation more explicit. For the other proposals, users who want to use REMPROP or REMF in situations which involve lists that might have duplicated elements would be able to do so more reliably.

Aesthetics

There is probably no particular aesthetic reason to think one of these solutions is better than the other, but having the issue nailed down is probably an aesthetic improvement.

Discussion

This issue, first brought up in Cleanup almost a year ago, got lost.

Pitman is agnostic on this for now. There are advantages to both. If everybody already implements REMOVE-ONE, that would seem the way to go.

"If we're going to extend Common Lisp to allow duplicated indicators on plists, we should do it for all the property list functions, not just REMF and REMPROP."

Edit History