all? or perhaps predicates that accept multiple args

Started by Sammo, March 31, 2011, 04:05:30 AM

Previous topic - Next topic

Sammo

Is there a simple and readable way of applying a predicate to multiple arguments? Perhaps something like:
(all? integer? 1 2 3 "string")
I know I can write:
(apply and (map integer? (list 1 2 3 "string")))
but, actually, I'd like to just write
(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

cormullion

#1
What about:


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


or


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

Kazimir Majorinc

#2
Additionally, if you insist on minimal syntax, you can play with fexprs (macros).


(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:
(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;
http://kazimirmajorinc.com/\">WWW site; http://kazimirmajorinc.blogspot.com\">blog.

Sammo

#3
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

William James

#4
This works for me:



(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