Programming Style & (eval ...)
Posted: Tue Jul 22, 2008 8:23 am
Hello all. I've been using Lisp in various forms for the last few years, but I've only recently started to really get into it. I find that for me to really get to know a language it helps to write some common libraries in it, so I decided to start porting some of Haskell's list library functions into Lisp. I ran into a problem right away though when trying to write all which takes a predicate and a list, returning true when all the elements in the list satisfy the predicate. So, for example
My first thought was that this is just a fold of the and operation into the result of mapping the predicate over the list. That means basically applying and to all the list elements, so in my ignorance I tried to do:
But of course that doesn't work because and isn't a function, it's a macro. So the solution I eventually discovered was:
Which leads me to my question: is it considered acceptable style to use eval to do something like this? I typically shun the use of eval in other languages, because it's usually just a cheap way of getting something done which could be handled in more elegant ways, but with the data-is-code orientation of Lisp, is this a common tactic to employ?
I'd also be interested to see any alternate implementations of and; I thought it might be cool to have a macro that expanded into [using the example above] (and t t t t nil) but I can't seem to make it happen. My best guess was
But that doesn't work because r is unbound -- which I think is because it doesn't exist in the environment into which the macro is expanded. However, even if I define an r using let before using the macro, it still doesn't work, not that that would be what I wanted anyway.
Thanks for any advice!
Code: Select all
CL-USER> (all #'(lambda (x) (= (mod x 2) 0)) '(2 2 4 8 6 0))
T
CL-USER> (all #'(lambda (x) (= (mod x 2) 0)) '(2 2 4 8 6 1))
NIL
Code: Select all
(apply 'and (mapcar #'evenp '(2 4 6 8 9))) => nil
Code: Select all
(defun all (f l)
(let ((r (mapcar f l)))
(eval `(and ,@r))))
I'd also be interested to see any alternate implementations of and; I thought it might be cool to have a macro that expanded into [using the example above] (and t t t t nil) but I can't seem to make it happen. My best guess was
Code: Select all
(defmacro all (f l)
`(let ((r (mapcar ,f ,l)))
(and ,@r)))
Thanks for any advice!