[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Some easy ones (?)



    Summary: The "no repeated names" rule removes a potential ambiguity
    for let; let* doesn't have that ambiguity..  Since they are different,
    exempting let* from the rule merely acknowledges their difference
    rather than introducing an exception.  Repeated variable names are
    better than some obvious alternatives.

OK, we agree that the main ambiguity that this clarification is trying
to address comes up only in the parallel-binding forms and not in the
sequential-binding forms.  So it is possible to come up with rules that
would allow the same variable to be bound N times in a single LET* form
without ambiguity.  Nobody is claiming that this is impossible.

I am suggesting that repeatedly binding the same variable within a
single binding form is an inherently confusing thing to do and that we
shouldn't introduce an exception into what otherwise could be a clean
and simple rule -- a variable is bound only once by any one binding
form -- in order to make this weird style possible.  (It may be that you
find this less confusing than I do because you think of LET* as nested
LAMBDAS while I think of it as a funny kind of LET, but I don't think
I'm alone in this.)

One nasty issue we would have to face if we allowed LET* to bind the
same variable multiple times is what to do about declarations that
affect the multiply-bound variable.  This is particularly nasty if we go
with the proposed scheme (any of them) that ties such declarations tot
he scope of the variable being bound.  Now you've got two or more scopes
for variable FOO, and only one place to put the declaration.  In this
case, I think that nested LET* forms would indeed be less confusing.

Your example of code that is best expressed with multiple rebindings in
a LET* is unconvincing to me.  I don't understand exactly what you mean
by "successively refining" an object, and I find your code example quite
confusing not only are you referring to two different locally-bound
variables, both named SUCCESS, but you've got free references to SUCCESS
and FAILURE in there as well.  I can sort this out, but in the presence
of a declaration or two, it might be pretty tough.

    (let* ((success (build-success code1 success failure))
           (failure (build-failure code2 success failure))
           (success (build-success code3 success failure)))
      <body>)

So, to answer your question, I do find the version with three SETQs much
easier to follow, and a version with three nested LET forms would be
better if it is really important to do this with rebinding and not with
SETQ.

So I still have not seen any code where multiple rebinding within a LET*
is the least confusing way to do something.  I admit that this is a
matter of taste and that reasonable people may differ on this, but I
suspect your proposed example would be confusing to a substantial
fraction of Common Lisp programmers, which makes it bad style in
general.

I don't want to get into an argument about style -- at least not on this
mailing list.  My point is simply that allowing multiple use of the same
variable in a single LET* does break what would otherwise be a simple
and uniform rule, it hairs up the declaration scoping rules, and there's
no good reason to allow this since in the rare case where you want to do
this there are alternatives that are at least as good and arguably
better.

-- Scott