Page 1 of 1

all? or perhaps predicates that accept multiple args

Posted: Thu Mar 31, 2011 11:05 am
by Sammo
Is there a simple and readable way of applying a predicate to multiple arguments? Perhaps something like:

Code: Select all

(all? integer? 1 2 3 "string")
I know I can write:

Code: Select all

(apply and (map integer? (list 1 2 3 "string")))
but, actually, I'd like to just write

Code: Select all

(integer? 1 2 3 "string")
which would return false (in this case because not all args are integers), or true (when all args are, in fact, integers).

It would be great if all predicates accepted multiple arguments.

Thanks,
-- Sam

Re: all? or perhaps predicates that accept multiple args

Posted: Thu Mar 31, 2011 6:25 pm
by cormullion
What about:

Code: Select all

 (exists integer? (list 1 2 3 "string"))
;-> 1
or

Code: Select all

(for-all integer? (list 1 2 3 "string"))
;-> nil

Re: all? or perhaps predicates that accept multiple args

Posted: Thu Mar 31, 2011 11:30 pm
by Kazimir Majorinc
Additionally, if you insist on minimal syntax, you can play with fexprs (macros).

Code: Select all

(setf [print.supressed] true [println.supressed] true)      ; ----
(load "http://instprog.com/Instprog.default-library.lsp")   ; only println= used
(setf [print.supressed] nil [println.supressed] nil)        ; ----

(define-macro (flat-for-all)
  (letn((L (args))
        (r (cons 'and (map (lambda(x)(list (first L) x)) (rest L)))))
       (print "{" r "}=")
       (eval r)))
  
(println= (flat-for-all integer? 1 "hugo") "\n")

(dolist (i '(integer? float? string? list?))
  (letex((old-predicate i)
         (new-predicate (sym (push "s" (string i) -2)))) ;float?->floats?

        (define-macro (new-predicate)
                      (eval (append '(flat-for-all old-predicate) 
                                     (args))))
                                     
        (println= new-predicate )))

(println= "\n" (integers? 1 2 "hugo") "\n"
               (integers? 1 2 3 4)    "\n"
               (floats? 1.5 6.1)      "\n"
               (strings? "hi" "ho"))
Output:

Code: Select all

(flat-for-all integer? 1 "hugo")={(and (integer? 1) (integer? "hugo"))}=nil;

integers?=(lambda-macro () (eval (append '(flat-for-all integer?) (args))));
floats?=(lambda-macro () (eval (append '(flat-for-all float?) (args))));
strings?=(lambda-macro () (eval (append '(flat-for-all string?) (args))));
lists?=(lambda-macro () (eval (append '(flat-for-all list?) (args))));

(integers? 1 2 "hugo")={(and (integer? 1) (integer? 2) (integer? "hugo"))}=nil;
(integers? 1 2 3 4)={(and (integer? 1) (integer? 2) (integer? 3) (integer? 4))}=true;
(floats? 1.5 6.1)={(and (float? 1.5) (float? 6.1))}=true;
(strings? "hi" "ho")={(and (string? "hi") (string? "ho"))}=true;

Re: all? or perhaps predicates that accept multiple args

Posted: Fri Apr 01, 2011 3:06 pm
by Sammo
Thanks, cormullion, for the idioms using exists? and for-all. They are certainly cleaner than my "(apply and (map ...) version.

But, Kazimir, your solution is precisely what I was seeking. After creating the various macros, the syntax is as simple as can be, and, by expanding as an explicit and expression and then evaluating that expression, the function returns nil as soon as it encounters an argument for which the predicate is not true.

Thank you very much.
-- Sam

Re: all? or perhaps predicates that accept multiple args

Posted: Tue Mar 06, 2012 9:30 am
by William James
This works for me:

Code: Select all

(define (for-all-args func)
  (for-all func (args)))

> (for-all-args number? 2 3 4 5)
true

> (for-all-args number? 2 3 'not 5)
nil