is it possible to write a strict AND function?

Discussion of Common Lisp

is it possible to write a strict AND function?

Postby yesimthetaxman » Thu Jul 07, 2011 7:22 pm

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...
yesimthetaxman
 
Posts: 10
Joined: Thu Jul 07, 2011 7:02 pm

Re: is it possible to write a strict AND function?

Postby wvxvw » Thu Jul 07, 2011 11:10 pm

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:
Code: Select all
(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
Last edited by wvxvw on Thu Jul 07, 2011 11:33 pm, edited 2 times in total.
wvxvw
 
Posts: 127
Joined: Sat Mar 26, 2011 6:23 am

Re: is it possible to write a strict AND function?

Postby smithzv » Thu Jul 07, 2011 11:16 pm

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

Code: Select all
(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.
smithzv
 
Posts: 94
Joined: Wed Jul 23, 2008 11:36 am

Re: is it possible to write a strict AND function?

Postby Paul » Fri Jul 08, 2011 6:35 am

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:
Code: Select all
(defun my-and (x y) (and x y))
Paul
 
Posts: 106
Joined: Tue Jun 02, 2009 6:00 am

Re: is it possible to write a strict AND function?

Postby gugamilare » Fri Jul 08, 2011 10:36 am

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:
Code: Select all
(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


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.
gugamilare
 
Posts: 406
Joined: Sat Mar 07, 2009 6:17 pm
Location: Brazil

Re: is it possible to write a strict AND function?

Postby wvxvw » Fri Jul 08, 2011 1:23 pm

Oh, sorry, it wasn't just a bit wrong, it was a whole lot wrong :) Well...
Code: Select all
(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.
wvxvw
 
Posts: 127
Joined: Sat Mar 26, 2011 6:23 am

Re: is it possible to write a strict AND function?

Postby Paul » Fri Jul 08, 2011 4:50 pm

Multi-arg version is just
Code: Select all
(defun hungry-and (&rest args) (every #'identity args))
Paul
 
Posts: 106
Joined: Tue Jun 02, 2009 6:00 am

Re: is it possible to write a strict AND function?

Postby wvxvw » Fri Jul 08, 2011 11:59 pm

Oh, right, I for whatever reason imagined that the first argument is mandatory.
wvxvw
 
Posts: 127
Joined: Sat Mar 26, 2011 6:23 am

Re: is it possible to write a strict AND function?

Postby gugamilare » Sat Jul 09, 2011 10:26 am

wvxvw wrote:Oh, sorry, it wasn't just a bit wrong, it was a whole lot wrong :) Well...
Code: Select all
(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.


That won't work either, or is not a function.
Calling (and) returns t, so (hungry-and) should also return t.


One might want a compiler macro of hungry-and:

Code: Select all
(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 :P).
gugamilare
 
Posts: 406
Joined: Sat Mar 07, 2009 6:17 pm
Location: Brazil

Re: is it possible to write a strict AND function?

Postby wvxvw » Sun Jul 10, 2011 1:37 am

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).
wvxvw
 
Posts: 127
Joined: Sat Mar 26, 2011 6:23 am

Next

Return to Common Lisp

Who is online

Users browsing this forum: Google [Bot] and 2 guests

cron