Subject: Re: Looking for a LISP function or macro ...
From: Erik Naggum <erik@naggum.no>
Date: 1998/09/19
Newsgroups: comp.lang.lisp
Message-ID: <3115185220022535@naggum.no>

* Kent M Pitman <pitman@world.std.com>
| So would I if not for the fact that these functions (or even their
| negations) aren't used much, and are totally easy to write yourself
| if missing. 

  "it's easy to write it yourself" is the Scheme argument.  for a single
  function, it's hard to refute, except for "why _should_ programmers
  everywhere need to do it for themselves?".  multiplied by thousands of
  functions, it doesn't really work that well, anymore.  moreover, I have
  yet to see an implementation that does away with the closure consing and
  function call overhead of COMPLEMENT in _all_ cases, which I doubt is
  even possible, so to write these functions _well_ would require writing
  the internals yourself, or you penalize people for their needs.  that's
  not what I associate with Common Lisp.

  a quick scan of my last project's source (120K, kept small through very
  hard work), shows that I found these -IF-NOT functions useful:

      DELETE-IF-NOT	of UPPER-CASE-P, to retain initials
      REMOVE-IF-NOT	of UPPER-CASE-P
      POSITION-IF-NOT	of WHITESPACE-CHAR-P  (for a non-consing TRIM)
      MEMBER-IF-NOT	of EMPTY, a test for a blank line, etc
		    and of NULL, to remove initial NILs in a list

  in all of these cases, I would either cons up a closure with COMPLEMENT,
  write a new function with the reversed sense without closure consing or
  extra function call overhead, or _hope_ there's a compiler macro that
  reverts to internal -IF-NOT functions.  what, precisely, is gained by
  removing these functions?  I'd say "purity of design", and that would
  have been valid if such was an expressed goal of the language, and it
  didn't have serious costs associated with it.
  
| It's clear the :TEST-NOT arguments are a semantic problem that has to be
| removed.

  as I have already stated, but once again for the record: :TEST-NOT should
  go, and this I have thought for years.  removing :TEST-NOT would not be
  done out of "purity of design" concerns, but out of concern for the fuzzy
  semantics of specifying both :TEST and :TEST-NOT, which might easily
  happen when writing the kind of functions that are suggested replacements
  for REMOVE-IF-NOT.  since that is possible, we have a real conflict that
  cries out for a solution.  I don't _like_ the name "complement" at all,
  but if I can bury it sufficiently, I hope I won't notice it sticking out.

| And users aren't exactly screwed if they do go away some year.  I
| didn't test the following, but imagine it or something like it would
| work, both today and years from now when remove-if-not goes away.
| 
| (eval-when (:execute :compile-toplevel :load-toplevel)
|   (when (fboundp 'remove-if-not)
|     (pushnew :remove-if-not *features*)))
| 
| #-remove-if-not
| (proclaim '(inline remove-if-not)) ;avoid overhead of extra function call
| 
| #-remove-if-not
| (defun remove-if-not (predicate sequence &rest keys &key &allow-other-keys)
|   (apply #'remove-if (complement predicate) sequence keys))

  once upon a time, you said something to the effect that Common Lisp saved
  you heaps of code that you previously had had to add to every project.
  we're moving backwards, now, where people have to add such code.  users
  _are_ screwed in many ways by this COMPLEMENT business.  debuggability
  goes down, performance is hit, etc, etc.  to re-supply REMOVE-IF-NOT
  after X3J13 takes it away needs reimplementing the function, not just
  slapping a couple wrappers around existing functions and hope nobody will
  notice that they can no longer fix bugs in the predicate function and
  continue, or that APPLY crops up much more often than it should during
  profiling.  an implementation that sports compiler macros that attempt to
  make REMOVE-IF fast by pre-determining keyword arguments would not be
  able to optimize the call unless COMPLEMENT itself were to be used in the
  _actual_ form.  thus, you make code much less readable in order to save
  on a "bloat" factor that is about two order of magnitude smaller than
  that of C++ or Java.

| Anyway, my point is that the few users who even use these functions can
| EASILY compensate for their absence.

  I take it that no study of the effects of the introduction of COMPLEMENT
  has been made.  COMPLEMENT has _very_ high costs.  they have _not_ been
  defended, nor have they been compared to the gains from removing -IF-NOT,
  if any.  as I see it, COMPLEMENT is a wanton waste of resources.  I have
  no qualms about spending lots of resources for a good reason; it's only
  the _wanton_ part I object to.

| And probably, if/when we do remove them, we'll somewhere publish the
| workaround code so users don't even have to do that much work.

  well, _I'm_ certain that vendors will protect user investments even if
  the committee abandons that goal.

  take :TEST-NOT and be satisfied, is my suggestion.  don't touch -IF-NOT.

#:Erik
-- 
  ATTENTION, all abducting aliens!  you DON'T need to RETURN them!