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

Changes to MEMBER, ASSOC, etc.

RMS failed to note in his message the following relevant points.

* The proposed definitions for MEMBER, ASSOC, etc. are compatible with all
  the cases of the current ASSOC except in the case of searching for list
  or string in list structure. Since Maclisp has no strings, Maclisp 
  compatibility is affected only in the case where people do

	(MEMBER '(B C) '((A B) (B C) (C D)))

  which in Maclisp used to return ((B C) (C D)) and under the proposed 
  definition would return NIL. On the LispM, the additional case of doing

	(MEMBER "BAR" '("FOO" "BAR" "BAZ"))

  which used to return ("BAR" "BAZ") would return NIL. Under the proposed
  standard, this would return NIL.

* In both of the cases written above, you can simply mechanically rewrite 
  your code. eg,

	(MEMBER '(B C) '((A B) (B C) (C D)) :TEST #'EQUAL)
    or  (MEMBER "BAR"  '("FOO" "BAR" "BAZ") :TEST #'EQUAL)

  In the cases where you've written

	(MEMBER C '(#/A #/B #/C))
    or  (MEMBER N '(1 2 3 4))
    or  (MEMBER X '(1.0 2.0 3.0))

  you need change nothing, you'll just find that in some implementations your
  code may run a little faster.

  The only thing that's in question is what the default test is.

* The reason for changing the default test (which will be by a new function
  EQL, which is like EQ except it can also compare characters or numbers)
  is that it will allow searches for numbers and characters (which is believed
  to be the most common use of MEMBER) to be more conveniently expressed.
  eg, it used to be that

	(MEMQ C '(#/A #/B #/C #/D))

  was guaranteed to work only on the LispM because in Maclisp numbers were not
  necessarily EQ and could not be searched for in some cases by MEMQ. (It 
  happens to work in some cases, but not all of them). The only alternative
  previously was to write

	(MEMBER C '(#/A #/B #/C #/D))

  which compiles inefficiently because it invokes an EQUAL test rather than
  a simpler test. Similar arguments can be made about searching for flonums.

  In the rarer cases of searching for strings or s-expressions, the intent
  of the current proposed definition is that you'd then use the clumsier 
  case of (MEMBER thing list :TEST test), specifying #'EQUAL, #'STRING-EQUAL,
  or whatever.

The :TEST argument will remain; that functionality is not in question. The
real questions which RMS is getting at are the following two:

(A) If you had no code you were worried about keeping compatible and you were
    just writing code from scratch, do you think EQL or EQUAL would be the more
    reasonable default predicate for MEMBER to use.

(B) If you have code which you want to run as easily as possible, do you
    consider the cost of locating the places which require this small change 
    from (MEMBER x y) to (MEMBER x y :TEST #'EQUAL) to be too much of a price 
    to pay for item A.

    Keep in mind that this will likely not be the only incompatible change 
    proposed by Common Lisp, so if you're thinking about the binary question
    of "Will my code run without my messing with it?" there is a fair chance
    the answer will be no anyway.