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

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))
    0)

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.