From: Jeff
Subject: Applying a function to a list of functions
Date: 
Message-ID: <cfgf2t$ton@odah37.prod.google.com>
I'm sure that what I want here is extremely simple to do and I'm just
missing a CL function... I'd like to pass the same argument to a list
of functions and apply those results (as a list) to another function --
at runtime. For example:

; Some functions
(setf alpha #'alpha-char-p)
(setf digit #'digit-char-p)

; A list of the above functions
(setf functions (list alpha digit))

; Test to see if 'c' is true for any item in the list
(defun is-alpha-numeric (c)
(apply #'or (mapcar #'(lambda (f c) (funcall f c)))
functions c))

Hopefully this makes sense. Yes, I know about alphanumericp, but this
will be used for far more, and this is a trivial example. MAPCAR would
normally be simple enough here, however, it needs a secondary list. Is
there a version of MAPCAR that can apply just one item across the board
instead of a list? I'm hoping that I don't have to come up with my own
version of #'apply or #'or to get this to work.

As a secondary wish, if there was a way to not force each of the
functions to be evaluated (given that I will be using #'or) that would
be nice. But this is hardly a requirement.
Any suggestions appreciated. Thanks!

Jeff

From: Marco Baringer
Subject: Re: Applying a function to a list of functions
Date: 
Message-ID: <m2d61ww4ac.fsf@convey.it>
"Jeff" <···@insightbb.com> writes:

> I'm sure that what I want here is extremely simple to do and I'm just
> missing a CL function... I'd like to pass the same argument to a list
> of functions and apply those results (as a list) to another function --
> at runtime. For example:

to do exactly "pass the same argument to a list of functions and apply
those results (as a list) to another function" i'd suggest:

(loop for func in functions
      collect (funcall func args) into values
      finally (return (apply other-function values)))

or, in a "functional" style:

(apply other-function
       (mapcar (lambda (func)
                 (funcall func args))
               functions))

having said that, if you all want is to "Test to see if 'c' is true
for any item in the list":

(some (lambda (func)
        (funcall func c))
      functions)

> As a secondary wish, if there was a way to not force each of the
> functions to be evaluated (given that I will be using #'or) that would
> be nice. But this is hardly a requirement.

you really lost me here.

-- 
-Marco
Ring the bells that still can ring.
Forget your perfect offering.
There is a crack in everything.
That's how the light gets in.
     -Leonard Cohen
From: Pascal Costanza
Subject: Re: Applying a function to a list of functions
Date: 
Message-ID: <cfggc3$at0$1@newsreader2.netcologne.de>
Jeff wrote:

> ; Test to see if 'c' is true for any item in the list
> (defun is-alpha-numeric (c)
> (apply #'or (mapcar #'(lambda (f c) (funcall f c)))
> functions c))

This is something for the do-everything-with-LOOP department:

(defun is-alpha-numeric (c)
   (loop for f in functions
         thereis (funcall f c)))

However, if you don't like LOOP you can also say this:

(defun is-alpha-numeric (c)
   (some (lambda (f) (funcall f c))
         functions))

Note that is-alpha-numeric-p would a better name. Names ending in -p 
indicate a predicate.

Further note that OR is not a function, so you can't say #'or. (That's 
why you use SOME or THEREIS instead.)



Pascal

-- 
Tyler: "How's that working out for you?"
Jack: "Great."
Tyler: "Keep it up, then."
From: Pascal Bourguignon
Subject: Re: Applying a function to a list of functions
Date: 
Message-ID: <87fz6sgmwg.fsf@thalassa.informatimago.com>
"Jeff" <···@insightbb.com> writes:

> I'm sure that what I want here is extremely simple to do and I'm just
> missing a CL function... I'd like to pass the same argument to a list
> of functions and apply those results (as a list) to another function --
> at runtime. For example:
> 
> ; Some functions
> (setf alpha #'alpha-char-p)
> (setf digit #'digit-char-p)
> 
> ; A list of the above functions
> (setf functions (list alpha digit))
> 
> ; Test to see if 'c' is true for any item in the list
> (defun is-alpha-numeric (c)
> (apply #'or (mapcar #'(lambda (f c) (funcall f c)))
> functions c))

> Hopefully this makes sense.

You're banging your head on one of the few pitfalls of Common-Lisp: 

+---------------------------------------------------------------------+
| OR is not a function, it's a macro, therefore you cannot apply it!  |
+---------------------------------------------------------------------+

The solution is to add your own OR function:

(defparameter alpha #'alpha-char-p)
(defparameter digit #'digit-char-p)

; A list of the above functions
(defparameter functions (list alpha digit))
 
(defun pjb-or (&rest args)
  "or is not a function..."
  (do ((args args (cdr args)))
      ((or (car args) (null args)) (car args))))

(defun is-alpha-numeric (c)
 (apply (function pjb-or) (mapcar (lambda (f) (funcall f c)) functions)))


You don't need to use FUNCTION on LAMBDA.  LAMBDA is a macro that does
it for you.  What's more, you can use a lambda sexp in place of a
function in function calls:

    ((lambda (x y) (+ x y)) 1 2) --> 3


(I prefer to leave the reader alone and use (function f) instead of #'f).


If you don't declare a top-level variable  with DEFVAR or
DEFPARAMETER, then the effects of SETF is unspecified.

Note the difference between  DEFVAR and DEFPARAMETER (another pitfall):

(defvar x 1)
(defvar x 2)
(assert (= x 1))

But:

(defparameter y 1)
(defparameter y 2)
(assert (= y 2))


> Yes, I know about alphanumericp, but this
> will be used for far more, and this is a trivial example. MAPCAR would
> normally be simple enough here, however, it needs a secondary list. Is
> there a version of MAPCAR that can apply just one item across the board
> instead of a list? I'm hoping that I don't have to come up with my own
> version of #'apply or #'or to get this to work.
> 
> As a secondary wish, if there was a way to not force each of the
> functions to be evaluated (given that I will be using #'or) that would
> be nice. But this is hardly a requirement.
> Any suggestions appreciated. Thanks!

You could use REDUCE:

(defun is-alpha-numeric (c)
    (reduce (lambda (b f) (or b (funcall f c))) functions
            :initial-value nil #|for b|#))


-- 
__Pascal Bourguignon__                     http://www.informatimago.com/

Our enemies are innovative and resourceful, and so are we. They never
stop thinking about new ways to harm our country and our people, and
neither do we.
From: Ron Garret
Subject: Re: Applying a function to a list of functions
Date: 
Message-ID: <rNOSPAMon-75807D.13070012082004@nntp1.jpl.nasa.gov>
In article <··············@thalassa.informatimago.com>,
 Pascal Bourguignon <····@mouse-potato.com> wrote:

> You're banging your head on one of the few pitfalls of Common-Lisp: 
                                         ^^^
ROTFL.

> | OR is not a function,

But SOME is.  So is EVERY.  (And so is IDENTITY.)

rg
From: Pascal Bourguignon
Subject: Re: Applying a function to a list of functions
Date: 
Message-ID: <87u0v8f3ks.fsf@thalassa.informatimago.com>
Ron Garret <·········@flownet.com> writes:

> In article <··············@thalassa.informatimago.com>,
>  Pascal Bourguignon <····@mouse-potato.com> wrote:
> 
> > You're banging your head on one of the few pitfalls of Common-Lisp: 
>                                          ^^^
> ROTFL.
> 
> > | OR is not a function,
> 
> But SOME is.  So is EVERY.  (And so is IDENTITY.)

Yes, I always forget about them.  My emacs legacy...

-- 
__Pascal Bourguignon__                     http://www.informatimago.com/

Our enemies are innovative and resourceful, and so are we. They never
stop thinking about new ways to harm our country and our people, and
neither do we.