help-gnu-emacs
[Top][All Lists]
Advanced

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

Re: member returns list


From: Pascal J. Bourguignon
Subject: Re: member returns list
Date: Thu, 03 Sep 2015 07:17:41 +0200
User-agent: Gnus/5.13 (Gnus v5.13) Emacs/24.3 (gnu/linux)

Emanuel Berg <embe8573@student.uu.se> writes:

> Drew Adams <drew.adams@oracle.com> writes:
>
>> I don't understand the question. It always functions
>> the same way. Whether code uses it only to test
>> membership or to access the first tail that
>> corresponds is up to that code. But `member' behaves
>> ("functions") the same.
>
> It looks like this:
>
>     (member ELT LIST)
>
> When is it beneficial to, instead of just getting
> a `t' on a hit, to get a list that consists of ELT and
> everything eastward of ELT, in LIST?
>
> The `car' example I provided may look cool (?) but it
> isn't anything that cannot be done with "memberp",
> because obviously the car is known, otherwise one
> wouldn't be able to search for it.

But member* is like CL:MEMBER, and take :KEY and :TEST arguments that
could make the matched element quite different from the target.

    (member* 1 '(2 4 6 5 7 9) :test (lambda (a b) (evenp (- a b))))
    --> (5 7 9)

    (member* 3 '(1 4 9 16 25) :key (function sqrt) :test (function =))
    --> (9 16 25)


An other example:

    ;; define an order on colors:
    (defvar *order* '(red orange yellow green blue indigo violet))
    (defun le (a b) (member b (member a *order*)))
    (le 'orange 'blue)   --> (blue indigo violet)
    (le 'orange 'orange) --> (orange yellow green blue indigo violet)
    (le 'blue   'orange) --> nil


Yet another example, not using car, but second:

    (defun rps-wins-over (a b)
       (eql b (second (member a '(paper rock scissors paper)))))

    (rps-wins-over 'scissors 'paper) --> t
    (rps-wins-over 'paper 'scissors) --> nil


Another example:

    (let ((list '(1 2 3 4 5 6))
          (terminator 4))
       (ldiff list (member terminator list)))
    --> (1 2 3)


Another example: in the algorith to process include CPP directories, I
have a use of member value such as:

    (let ((include-directories (include-directories kind)))
      (when (eq directive :include-next)
        (setf include-directories (cdr (member (context-directory context)
                                               include-directories
                                               :test (function equal)))))
      (multiple-value-bind (path directory)
          (search-file-in-directories include-file include-directories kind 
directive)
        (cond ((eq t path) #|done|#)
              (path        (include path directory))
              (t           (cpp-error …)))))

Another example: since member returns the cons cell where the target
object is stored, we can update it.  For example, when implementing a
cache, I used something like:

    (defun update-cache (name)
      (let ((sl (member* name *cache* :key 'object-name  
                                     :test 'string-equal)))
        (if sl
           (setf (car sl) new-data)
           (push new-data *cache*))))




In CL, there's another predicate that returns a very useful value:
digit-char-p is specified to return the integer value of the digit
character:

   (digit-char-p #\4) --> 4
   (digit-char-p #\!) --> nil

In general, in CL, predicates are specified to return _generalized_
booleans, so implementation may return useful values for them too (but
it would be non-conforming to take advantage of those "useful" values).

-- 
__Pascal Bourguignon__                 http://www.informatimago.com/
“The factory of the future will have only two employees, a man and a
dog. The man will be there to feed the dog. The dog will be there to
keep the man from touching the equipment.” -- Carl Bass CEO Autodesk


reply via email to

[Prev in Thread] Current Thread [Next in Thread]