[racket] member et al.

From: Eli Barzilay (eli at barzilay.org)
Date: Thu Nov 11 13:14:57 EST 2010

25 minutes ago, Neil Toronto wrote:
> Eli Barzilay wrote:
> > Four minutes ago, Neil Toronto wrote:
> >> I think we should retire this truthiness business, replace cond's
> >> `=>' with something that lets you easily nest conds (I have a
> >> proposal ready for this, and it is awesome),
> > 
> > (a) how is this related?  (b) `=>' is not used to nest `cond's.
> You use it to have the same computed value available in both the
> test-expr and the then-body, which would otherwise require nested
> `cond's.

(Only if you want to use it multiple times, which is not too
frequent, far less than cases where `=>' are useful for.)

> I got inspired by the #:when form in `for' loops that flattens
> nesting, and wrote a `cond*' macro that allows this instead:
> (cond* [... some stuff ...]
>         #:with (define m ...)
>         [(... something about m ...)  (... something using m ...)]
>         ... more things referring to m ...)
> It's more general, since it doesn't require encoding the condition
> you want to test as a truthiness value. Also, the `define' doesn't
> have to be a `define' - it can be any legal expression.

So, you advocate eliminating `member' etc for predicates (why I
started with saying that this is much stickier than just adding a
`member?').  So we started with

  (cdr (assq x alist))

then Scheme upgraded this to

  (cond [(assq x alist) => cdr]
        [else #f])

and you suggest continuing with

  (cond #:with (define p (assq x alist))
        [(pair? p) (cdr p)]
        [else #f])

or, with more well-behaved proper sub lists

  (cond #:with (define p (assq x alist))
        [(not (eq? p #f)) (cadr p)]
        [else #f])

(Yes, you can still use `pair?' but that would be ugly for the same

I also wonder how many newbies (or people that just want to type less)
will fall into traps like

  (if (member? x l)
    (+ 1 (find x l))

My loud "ugh" should be expected now.

> It's flattened most of my numeric code. Numeric code often computes and 
> reacts to easily computable, approximate conditions first. When the easy 
> tests are inconclusive, it computes and reacts to progressively more 
> precise conditions that are more expensive.

(Sounds like srfi-2.)

> I've never heard this, and I am curious. How does truthiness in `and' 
> and `or' preserve proper tail calls?

Two minutes ago, Jay McCarthy 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.

Yeah -- and this is an obvious case.  There are more subtle cases
where it's important to preserve tail position.  (I think that Joe had
a post once on how nice it is when things work wrt tail calls without
forcing you to think about it or write more code.)

          ((lambda (x) (x x)) (lambda (x) (x x)))          Eli Barzilay:
                    http://barzilay.org/                   Maze is Life!

Posted on the users mailing list.