I am trying to write a simple boolean AND function that uses eager/strict evaluation. That is, I want both arguments to the AND function to be evaluated. I am able to write a function to simulate this using IF statements, but it is long, I am wondering if anyone has any ideas how to write a shorter, more elegant version that evaluates the two arguements and then AND's them...
is it possible to write a strict AND function?
18 posts · 4119 views
Re: is it possible to write a strict AND function?
Let's see if it helps, I'm not exactly sure where do you want to evaluate arguments, but I assumed that you didn't want to continue checking the arguments after you are sure about the result:
(defun hungry-and (x &rest y)
(format t "arguments: ~a~&" x) ; but the function will stop checking them
; once it sees first argument that evaluates to nil
(when x (when y (apply 'hungry-and y))))
(hungry-and :foo :bar 42 t nil "string") ; arguments are evaluated hereLast edited by wvxvw on , edited 2 times in total.
Re: is it possible to write a strict AND function?
Yeah, remember that for functions, all arguments will be evaluated prior to calling the function. This doesn't happen with AND because it is a macro (or special form).
This is kind of a FAQ and the common answer is to look at the EVERY function for AND and the SOME function for OR. You can also do this simply enough using REDUCE, or build your own function like...
This is kind of a FAQ and the common answer is to look at the EVERY function for AND and the SOME function for OR. You can also do this simply enough using REDUCE, or build your own function like...
(defun my-and (&rest args)
(cond ((not args)
;; There are no arguments, default to true
t )
(t (and (car args) (apply #'my-and (cdr args)))) ))
Note, we still use AND, it will still short circuit the recursion, but all of the arguments are evaluated before we ever call MY-AND.Re: is it possible to write a strict AND function?
yesimthetaxman wrote:I am trying to write a simple boolean AND function that uses eager/strict evaluation. That is, I want both arguments to the AND function to be evaluated. I am able to write a function to simulate this using IF statements, but it is long, I am wondering if anyone has any ideas how to write a shorter, more elegant version that evaluates the two arguements and then AND's them...If you just want a two-argument version:
(defun my-and (x y) (and x y))Re: is it possible to write a strict AND function?
wvxvw wrote:Let's see if it helps, I'm not exactly sure where do you want to evaluate arguments, but I assumed that you didn't want to continue checking the arguments after you are sure about the result:I didn't test it, but it seems your code is a bit wrong because it will always return nil. For instance, with only one argument, when X is true, it will see that Y is empty and return nil.(defun hungry-and (x &rest y) (format t "arguments: ~a~&" x) ; but the function will stop checking them ; once it sees first argument that evaluates to nil (when x (when y (apply 'hungry-and y)))) (hungry-and :foo :bar 42 t nil "string") ; arguments are evaluated here
Re: is it possible to write a strict AND function?
Oh, sorry, it wasn't just a bit wrong, it was a whole lot wrong
Well...
(defun hungry-and (x &rest y)
(format t "arguments: ~a~&" x) ; but the function will stop checking them
; once it sees first argument that evaluates to nil
(when x (every 'or y)))
A fixed version. Although, I must note that smithzv would also be wrong when called with empty list for example.Re: is it possible to write a strict AND function?
Multi-arg version is just
(defun hungry-and (&rest args) (every #'identity args))Re: is it possible to write a strict AND function?
Oh, right, I for whatever reason imagined that the first argument is mandatory.
Re: is it possible to write a strict AND function?
wvxvw wrote:Oh, sorry, it wasn't just a bit wrong, it was a whole lot wrongThat won't work either, or is not a function.Well...
A fixed version. Although, I must note that smithzv would also be wrong when called with empty list for example.(defun hungry-and (x &rest y) (format t "arguments: ~a~&" x) ; but the function will stop checking them ; once it sees first argument that evaluates to nil (when x (every 'or y)))
Calling (and) returns t, so (hungry-and) should also return t.
One might want a compiler macro of hungry-and:
(define-compiler-macro hungry-and (&rest args)
(let ((syms (loop repeat (length args) collect (gensym))))
`(let ,(mapcar #'list syms args)
(and ,@syms))))
(I just have a bad feeling about constructing a list at run time when that is not necessary Re: is it possible to write a strict AND function?
Even though 'or isn't a function you are allowed to use it with 'every, so it will work as advertised (at least it worked for me in SBCL and CLISP).
except for, as you quite righteously noted it won't work for empty list (and I did say I thought that the original 'and must take at least one argument). So, that is, of course my mistake. And well, OP wanted a function...
As an aside, I don't quite understand why is original 'and returns true if given no arguments, or why is there such an option at all. (That's to say I don't understand, not that it's wrong).
As an aside, I don't quite understand why is original 'and returns true if given no arguments, or why is there such an option at all. (That's to say I don't understand, not that it's wrong).
Re: is it possible to write a strict AND function?
wvxvw wrote:Even though 'or isn't a function you are allowed to use it with 'every, so it will work as advertised (at least it worked for me in SBCL and CLISP).Are you sure? It didn't work for me in SBCL, and the Hyperspec says the predicate must be a function designator.
wvxvw wrote:As an aside, I don't quite understand why is original 'and returns true if given no arguments, or why is there such an option at all. (That's to say I don't understand, not that it's wrong).Calling (or) is equivalent to asking: Is there some element of the empty list that classifies as true? Since there is nothing in the empty list, in particular there is nothing that classifies as true, so the answer is false.
Calling (and) is equivalent to asking: Do all elements of the empty list classify as true? That is true by vacuity. In logic, answering no to that question is the same as saying that there is an element in the empty list that classifies as false, that is, the empty list contains nil. Since that is obviously not true, the answer to the question is yes.
Re: is it possible to write a strict AND function?
I seriously did try it, though on Window machine, would that be an issue, also I remember that I tried it after with 'apply, and it didn't, so it was kind of strange? I could even post a screenshot of it working once I'm back there
But yes, I tried it now on Linux SBCL and it didn't work. Yes, it makes sense what you say. Also I remember that in error it gave about 'or it didn't mention it as a macro, it said it is a special operator, which would still qualify as a function probably?
Re: is it possible to write a strict AND function?
wvxvw wrote:I seriously did try it, though on Window machine,I was on Windows when I tried it
wvxvw wrote:[...] Also I remember that in error it gave about 'or it didn't mention it as a macro, it said it is a special operator, which would still qualify as a function probably?But or is a macro.
Re: is it possible to write a strict AND function?
wow there are so many ideas, thank you.
I think the problem with this question is that it is suppose to avoid higher order functions that do the work for you... apparently there is an elegant solution that uses only basic functions, no macros. once I figure it out I will post it here. I don't think functions such as "every" can be used. i think reduce is allowed though
I think the problem with this question is that it is suppose to avoid higher order functions that do the work for you... apparently there is an elegant solution that uses only basic functions, no macros. once I figure it out I will post it here. I don't think functions such as "every" can be used. i think reduce is allowed though
Re: is it possible to write a strict AND function?
turns out that the answer is actually quite simple:
(defun and-nl (a b) (and a b))
since arguments are evaluated before they are passed to the routine body we have an AND that forces the evaluation of both arguments to AND.
(defun and-nl (a b) (and a b))
since arguments are evaluated before they are passed to the routine body we have an AND that forces the evaluation of both arguments to AND.
Re: is it possible to write a strict AND function?
yesimthetaxman wrote:turns out that the answer is actually quite simple:Well, yes. I and many others assumed you wanted a function that would take as many arguments as you wanted, just like the macro and, which takes up from 0 arguments.
(defun and-nl (a b) (and a b))
since arguments are evaluated before they are passed to the routine body we have an AND that forces the evaluation of both arguments to AND.
Re: is it possible to write a strict AND function?
yesimthetaxman wrote:turns out that the answer is actually quite simple:Fourth post in this thread
(defun and-nl (a b) (and a b))
since arguments are evaluated before they are passed to the routine body we have an AND that forces the evaluation of both arguments to AND.
Re: is it possible to write a strict AND function?
ohh ya your right i didn't realize that lol