Subject: bug#28254: 26.0.50; SRFI-2 and-let*

From: Mark Oteiza <[email-masked]>
Date: Tue, 12 Sep 2017 16:21:34 -0400

On 12/09/17 at 08:44pm, Michael Heerdegen wrote:
> Mark Oteiza <[email-masked]> writes:
> 
> > > Not really related to your change, but: Maybe we should additionally
> > > say that THEN can refer to the bindings made in the VARLIST, but
> > > ELSE to none, not even to those that resulted in non-nil values
> > > before "failing".
> >
> > That's not true though--you can refer to the bindings in either branch:
> 
> Hmm, that feels strange.  FWIW, all the scheme implementations I looked
> at implemented it in a way that binding variables stops after the first
> nil.  OTOH I would expect that all bindings are only available from the
> THIS branch (this is my personal opinion).  In our case, we have
> something third: always all bindings are visible in the ELSEs, e.g.
> 
> (let ((z 1))
>   (if-let* ((nil) (z 100))
>       (doesnt-matter)
>     z))
> 
> ==> nil
> 
> That doesn't feel right.

Yeah, it's a product of how this is written as building a list
of shortcircuiting bindings instead of recursively or otherwise--not
sure if there's more to it than that.  I can't say I fully understood
the Guile implementation when I read it last.  Worth thinking about.

> In `internal--listify':
> isn't (or (listp form) (atom form)) always true?

Yes, that could instead be (or form (null form)). It's meant to catch
things like this:

  (should (equal nil (and-let* ((nil) (x 1)))))

> Secondly, in `internal--build-binding-value-form':
> How can it happen that (car binding) is an atom but not symbolp?  And if
> (car binding) == var is not a symbol, how does the returned binding make
> sense?

It's an expression, like a number.

  (should (equal 1 (and-let* ((2) (x 1)))))