[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

subst-if-not and nsubst-if-not, programming folk-lore

    Date: Sun, 6 Jul 86 14:48 EDT
    From: Brad Miller <miller@UR-ACORN.ARPA>

	Date: Sun, 29 Jun 86 19:42 EDT
	From: David C. Plummer <DCP@QUABBIN.SCRC.Symbolics.COM>

	These are really neat functions, and counterintuitive to boot.  One of
	our documentation people tried this:


	Now, when one tries subst-if-not, one gets a small surprise
    until one thinks about it a bit:

	    (let* ((item-list '(numbers (1.0 2 5/3) symbols (foo bar)))
		   (new (subst-if-not '3.1415 #'numberp item-list)))
	      (values new item-list))
	    => 3.1415
	       (NUMBERS (1.0 2 5/3) SYMBOLS (FOO BAR))

	and nsubst-if-not gives the same thing

	, i.e., the list is NOT destructed.  A careful reading explains why: the
	item-list is indeed not a number, and therefore it gets substituted (but
	you can't substitute the entire list, so you don't modify it).

	What the person probably wanted is to replace the non-null atomic
	leafs.  I'm not sure what to think.  One thing I'm thinking is that
	(n)subst-if-not is too counter-intuitive to be worth having in the
	language, even for completeness.  At the very list, I think the
	book/manual should carefully discuss this issue to people don't get
	confused for years.

    Good point. To point out the obvious: perhaps [n]subst-if-not should not
    try to match subtrees? (which would include nil cdrs).....
    That would still give a useful function on leaves.... Your example would
    have been evaluated to:
	    (3.1415 (1.0 2 5/3) 3.1415 (3.1415 3.1415))
    which is a bit more intuitive, I think, though not precisely an inverse
    to subst-if, which as you suggested, can be quite non-intuitive (and
    perhaps unnecessary)....

No, I think if [n]subst-if-not stay in the language then their
definitions should not change.  Conses are just as valid as any other
data, and changing their definition could make them even more confusing.
I'm not (currently) advocating removing them from the language.  I am
advocating documenting this pitfall.  It may want to say that "we"
currently believe code is easier to write, undersetand and maintain if
[n]subst-if is used intead of [n]subst-if-not and give the example
	(nsubst-if 3.1415 #'(lambda (item)
			      (and item
				   (atom item)
				   (not (numberp item))))
The screw here is that NIL in the CAR isn't distinguished from NIL in
the CDR, which may be a more fundamental problem.  Doing the CDR, even
though it may be NIL has several valid applications, so it shouldn't be
dismissed lightly.