From: Peter Berck
Subject: (Q) use of EVAL.
Date: 
Message-ID: <1993Feb02.123827.12752@kub.nl>
Hi,

Sorry to interrupt the discussion about lisp being a main-stream
language (doesn't lisp mean, Lisp Is Simply Perfect?), but
I wondered if the following is accepted use of EVAL. I checked
the FAQ, but that didn't really help.

I want to be able to access no matter which slot from an instance
of some class, and be able to do some search operation on it.
I have something that looks like this:

(defun select (search-string slot)
  "select something."
  (dolist (an-instance instances-list)
     ;; I want something like (string-match-p "foo?bar" (name an-instance))
     ;; but 'name could be another slot specified by the user...
     (if (eval `(string-match-p ,search-string (,slot ,an-instance)))
        (do-something)
        (do-nothing)
	)))

I have this nagging feeling I am going about things the wrong way,
but I can't put my finger on it.

Thanx
-Peter

------------------------------------------------------------------
······@kub.nl
(format t "~&~{~<~%~1:;~a~>~^,~}.~%"
        '(DoD#-337 cx-500 Sonic-Youth The-Icicle-Works Lush
          Dante-Alighieri Guinness))

From: John Tang Boyland
Subject: Re: (Q) use of EVAL.
Date: 
Message-ID: <1kmipd$otk@agate.berkeley.edu>
In article <······················@kub.nl>, ······@kub.nl (Peter Berck) writes:
|> 
|> 
|> I want to be able to access no matter which slot from an instance
|> of some class, and be able to do some search operation on it.
|> I have something that looks like this:
|> 
|> (defun select (search-string slot)
|>   "select something."
|>   (dolist (an-instance instances-list)
|>      ;; I want something like (string-match-p "foo?bar" (name an-instance))
|>      ;; but 'name could be another slot specified by the user...
|>      (if (eval `(string-match-p ,search-string (,slot ,an-instance)))
|>         (do-something)
|>         (do-nothing)
|> 	)))
|> 
|> I have this nagging feeling I am going about things the wrong way,
|> but I can't put my finger on it.
|> 
|> Thanx
|> -Peter
|> 
|> ------------------------------------------------------------------
|> ······@kub.nl
|> (format t "~&~{~<~%~1:;~a~>~^,~}.~%"
|>         '(DoD#-337 cx-500 Sonic-Youth The-Icicle-Works Lush
|>           Dante-Alighieri Guinness))

Your nagging feelings are correct: for starters, there's no reason you
have to use eval for the call to string-match-p.  At the very least you
should change the conditional to:
	(string-match-p search-string (eval `(,slot ,an-instance)))
But now, (assuming "slot" is not a macro) we can go one step further to:
	(string-match-p search-string 
                        (funcall (symbol-function slot) an-instance))
At this point we have got rid of "eval" but still make use of "symbol-function"
which is similarly suspect.  Since the only use for the symbol is to pick
off its symbol-function, we might as well push that back to the call and
require the function to be called as (select "foo?bar" #'name).
Then the conditional is
	(string-match-p search-string (funcall slot-func an-instance))
In fact we are now to the point where the whole function probably can be
defined as:
	(find search-string instances-list 
	      :test #'string-match-p 
	      :key slot-func)

John (·······@cs.berkeley.edu)
From: Barry Margolin
Subject: Re: (Q) use of EVAL.
Date: 
Message-ID: <1knkhlINNgct@early-bird.think.com>
In article <······················@kub.nl> ······@kub.nl writes:
>(defun select (search-string slot)
>  "select something."
>  (dolist (an-instance instances-list)
>     ;; I want something like (string-match-p "foo?bar" (name an-instance))
>     ;; but 'name could be another slot specified by the user...
>     (if (eval `(string-match-p ,search-string (,slot ,an-instance)))
>        (do-something)
>        (do-nothing)
>	)))

Ue functional programming, like this:

(defun select (search-string slot-accessor)
  (dolist (an-instance *instances-list*)
    (if (string-match-p search-string (funcall slot-accessor an-instance))
	(do-something)
	(do-nothing))))

The difference is that it is invoked as (select "foo?bar" #'slot-reader).

If you *really* want to let the user pass a symbol instead of a function,
then make a table that maps them to functions:

(defvar *accessor-table*
  `((slot1 . ,#'slot1)
    (slot2 . ,#'slot2)
    ...))

(defun select (search-string slot)
  (let ((slot-accessor (cdr (assoc slot *accessor-table*))))
    (if slot-accessor
	(dolist (an-instance *instances-list*)
	  (if (string-match-p search-string (funcall slot-accessor an-instance))
	      (do-something)
	      (do-nothing)))
	(error "Unknown slot ~S." slot))))
-- 
Barry Margolin
System Manager, Thinking Machines Corp.

······@think.com          {uunet,harvard}!think!barmar