[racket] member et al.

From: Mark Engelberg (mark.engelberg at gmail.com)
Date: Thu Nov 11 13:56:23 EST 2010

On Thu, Nov 11, 2010 at 9:56 AM, Jay McCarthy <jay.mccarthy at gmail.com> wrote:
> (define (andmap f l)
>  (if (empty? l)
>     #t
>     (and (f (first l)) (andmap f (rest l)))))
>
> If and has to return a boolean, then it leaves space on the stack to
> check if andmap returns a bool or to convert "truth" to #t. Thus this
> program goes from constant stack space to linear stack space.

I don't understand this point.

(define (andmap f l)
 (cond
   [(empty? l) #t]
   [(f (first l)) (andmap f (rest l))]
   [else #f]))

definitely returns a Boolean, while working with both "true
predicates" and "pseudo predicates", and works in constant stack
space.

If you really wanted and/or to definitely return booleans, there's no
reason they couldn't be implemented similarly, like this for a two arg
version:
(define-syntax-rule (and x y)
  (cond
    [x (if y #t #f)]
    [else #f]))

or more like andmap for the multiarg version.  Basically, you end up
doing one more test (against the final arg) than you would in the
existing scheme.

With such an implementation of and, you could implement andmap
directly using and, while getting a guaranteed Boolean.

So I don't see why there's any connection between making things return
Booleans and tail-call behavior.

Regardless of this point, I think that at least a case has been made
that there would be value to having member? alongside member, because
sometimes (especially in Typed Racket) it is useful to express
predicate intent.


Posted on the users mailing list.