[racket] member et al.

From: Jay McCarthy (jay.mccarthy at gmail.com)
Date: Thu Nov 11 13:57:59 EST 2010

On Thu, Nov 11, 2010 at 11:56 AM, Mark Engelberg
<mark.engelberg at gmail.com> wrote:
> 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)]

This 'if' introduces a stack frame that is not otherwise needed.

Jay

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



-- 
Jay McCarthy <jay at cs.byu.edu>
Assistant Professor / Brigham Young University
http://faculty.cs.byu.edu/~jay

"The glory of God is Intelligence" - D&C 93


Posted on the users mailing list.