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
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."
"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.
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
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.