[plt-scheme] define-union
On Fri, 18 Apr 2003, Anton van Straaten wrote:
> How about modifying your spec slightly to allow this:
>
> (define-union snark? (foo? bar? number?))
>
> ...which would allow you to use this:
>
> (define-syntax define-union
> (syntax-rules ()
> ((_ name (pred ...))
> (define (name x) (or (pred x) ...)))))
>
> ...which has the virtue of being very simple to implement and understand.
>
If you modify the spec just a little more, you don't need a macro at all.
You just need to be willing to use regular define rather than introducing
the new keyword define-union.
(define (union . predicates)
(lambda (item) (ormap (lambda (f) (f item)) predicates)))
(define snark? (union foo? bar? number?))
> (snark? (make-foo 'a 'b))
#t
> (snark? (make-bar 'c 'b #f))
#t
> (snark? 453)
#t
> (snark? 'snark)
#f
> (snark? "I'm a snark! Honest!")
#f
If you want the error-detection Robby added in, you can use this ugly guy:
(define (union . predicates)
(let* ([nonpredicate?
(lambda (p)
(if (and (procedure? p)
(procedure-arity-includes? p 1))
#f
p))]
[bad-val (ormap nonpredicate? predicates)])
(if (not bad-val)
(lambda (item) (ormap (lambda (f) (f item)) predicates))
(error 'union "not a predicate: ~e" bad-val))))
> (snark? (make-foo 'a 'b))
#t
> (snark? (make-bar 'c 'b #f))
#t
> (snark? 453)
#t
> (snark? 'snark)
#f
> (snark? "I'm a snark! Honest!")
#f
> (define mistake? (union number? cons))
union: not a predicate: #<primitive:cons>
Not pretty, but it works.
-jacob