From: Michael Greenberg
Subject: Style question:  do vs do* and let vs. let*
Date: 
Message-ID: <BPKBa.21753$io.367269@iad-read.news.verio.net>
When you use a 'do' or 'let', which form do you use when there is no
necessity to use one or the other.

For example

(let ((v1 1)
        (v2 2))
 ...)

would you use let or let*.  Why?

I was discussing this with a colleague today...I had been using 'let'.  He
thought that let* was better.  His argument was that it is more important to
highlight the need for parallel assignment rather then serial assignment
because the former case is more difficult to recognize.

I tend to agree with him.

Your opinions...

Michael Greenberg

From: Duane Rettig
Subject: Re: Style question:  do vs do* and let vs. let*
Date: 
Message-ID: <4znl4s6mp.fsf@beta.franz.com>
"Michael Greenberg" <··········@scr.siemens.com> writes:

> When you use a 'do' or 'let', which form do you use when there is no
> necessity to use one or the other.
> 
> For example
> 
> (let ((v1 1)
>         (v2 2))
>  ...)
> 
> would you use let or let*.  Why?
> 
> I was discussing this with a colleague today...I had been using 'let'.  He
> thought that let* was better.  His argument was that it is more important to
> highlight the need for parallel assignment rather then serial assignment
> because the former case is more difficult to recognize.
> 
> I tend to agree with him.
> 
> Your opinions...

I tend to use let rather than let*, because it is the more basic;
let* forms that have no declarations can always be constructed using
let forms, but not the other way around:

 (let* ((v1 1)
        (v2 2))
   ...)

is equivalent to

 (let ((v1 1))
   (let ((v2 2))
     ...))

However, the scope of this question is relatively narrow, because
there are other considerations; the addition of declarations might
color the outcome, as well as horizontal source code space (I might
use a let* to group a number of otherwise unrelated let's into one
form, in order to give myself a few extra columns of readability
toward the left side of the page).

-- 
Duane Rettig    ·····@franz.com    Franz Inc.  http://www.franz.com/
555 12th St., Suite 1450               http://www.555citycenter.com/
Oakland, Ca. 94607        Phone: (510) 452-2000; Fax: (510) 452-0182   
From: sv0f
Subject: Re: Style question:  do vs do* and let vs. let*
Date: 
Message-ID: <none-EDFDCD.11211830052003@news.vanderbilt.edu>
In article <·····················@iad-read.news.verio.net>,
 "Michael Greenberg" <··········@scr.siemens.com> wrote:

>When you use a 'do' or 'let', which form do you use when there is no
>necessity to use one or the other.
>
>For example
>
>(let ((v1 1)
>        (v2 2))
> ...)
>
>would you use let or let*.  Why?
>
>I was discussing this with a colleague today...I had been using 'let'.  He
>thought that let* was better.  His argument was that it is more important to
>highlight the need for parallel assignment rather then serial assignment
>because the former case is more difficult to recognize.

I use LET in these situations for a couple of reasons.

First, when I see LET* (or DO*), I assume there is a dependency
in the bindings being created and go off looking for it.  If
there is no such dependency, then this will be wasted effort --
a false alarm.

Second, I mentally rewrite LET* as nested LETs.  For example,
     (let* ((x 1)
            (y (1+ x))
       ...)
morphs (roughly) into
     (let ((x 1))
       (let ((y (1+ x))
         ...))
in my mind's eye.  For this reason, LET* feels more cumbersome
than LET.

Of course, these are just my defaults and your's are probably
different.

However, it is my sense that using LET (and DO) in default cases
is the community convention.  Anyone disagree?  You should only
violate such conventions when you feel strongly about an issue.
(For example, when forming predicates, I *always* append "-P" and
never just plain "P" because I think identifiers like "SYMBOLP"
look bad.)

On a related note, here's a problem that always trips me up.
As I said above, I use LET by default and LET* only when there
is a dependency in the (values of the) bindings being created.
Which is to say I typically interpret LET to me "move along,
there's no dependency here to see."  However, *sometimes* LET
means "compute the values of these new bindings in parallel."
This occasionally leads me to misinterpret the true intention
behind the use of LET in code and that others.

Anyone else suffer from this gotcha?
From: Pascal Costanza
Subject: Re: Style question:  do vs do* and let vs. let*
Date: 
Message-ID: <bb7uk6$u7g$1@f1node01.rhrz.uni-bonn.de>
Michael Greenberg wrote:
> When you use a 'do' or 'let', which form do you use when there is no
> necessity to use one or the other.
> 
> For example
> 
> (let ((v1 1)
>         (v2 2))
>  ...)
> 
> would you use let or let*.  Why?
> 
> I was discussing this with a colleague today...I had been using 'let'.  He
> thought that let* was better.  His argument was that it is more important to
> highlight the need for parallel assignment rather then serial assignment
> because the former case is more difficult to recognize.

I use let as the default. I recall reading somewhere that the most 
important thing here is that you are consistent with yourself (or with 
the group of people, or with the code at hand).

In my mental model, let* is an overspecification when in fact the order 
of assignment just doesn't matter. Possibly, implementations can also 
optimize the parallel case better than the sequential one, but I am just 
guessing...

Pascal

-- 
Pascal Costanza               University of Bonn
···············@web.de        Institute of Computer Science III
http://www.pascalcostanza.de  R�merstr. 164, D-53117 Bonn (Germany)
From: Kenny Tilton
Subject: Re: Style question:  do vs do* and let vs. let*
Date: 
Message-ID: <3ED7833D.8070507@nyc.rr.com>
> Michael Greenberg wrote:
> 
>> When you use a 'do' or 'let', which form do you use when there is no
>> necessity to use one or the other.

Do/let. esp, with let, which I rarely use anyway (it's so 
dis-functional!), let* is really unusual for me to use. These are 
bindings I am setting up for use in the body, I don't want them to be 
part of the body (by having bindings use earlier bindings). So to me 
these local bindings are naturally independent of eachother and then 
parallel is the normal model, sequential is the oddball.

And that is why sequential let gets the scary *.



-- 

  kenny tilton
  clinisys, inc
  http://www.tilton-technology.com/
  ---------------------------------------------------------------
"Everything is a cell." -- Alan Kay
From: Nils Goesche
Subject: Re: Style question:  do vs do* and let vs. let*
Date: 
Message-ID: <87d6i0h0uk.fsf@darkstar.cartan>
Pascal Costanza <········@web.de> writes:

> Michael Greenberg wrote:

> > I was discussing this with a colleague today...I had been
> > using 'let'.  He thought that let* was better.  His argument
> > was that it is more important to highlight the need for
> > parallel assignment rather then serial assignment because the
> > former case is more difficult to recognize.
> 
> I use let as the default. I recall reading somewhere that the
> most important thing here is that you are consistent with
> yourself (or with the group of people, or with the code at
> hand).
> 
> In my mental model, let* is an overspecification when in fact
> the order of assignment just doesn't matter. Possibly,
> implementations can also optimize the parallel case better than
> the sequential one, but I am just guessing...

Note that ``parallel�� and ``sequential�� refer only to scope in
Common Lisp here.  Unlike Scheme, the order of evaluation is
specified and the same in both cases.

Regards,
-- 
Nils G�sche
Ask not for whom the <CONTROL-G> tolls.

PGP key ID #xD26EF2A0
From: Janis Dzerins
Subject: Re: Style question:  do vs do* and let vs. let*
Date: 
Message-ID: <twk4r3c1lfh.fsf@gulbis.latnet.lv>
"Michael Greenberg" <··········@scr.siemens.com> writes:

> When you use a 'do' or 'let', which form do you use when there is no
> necessity to use one or the other.

This has already been throroughly discussed here.  Please use Google.

-- 
Janis Dzerins

  If million people say a stupid thing, it's still a stupid thing.
From: Kaz Kylheku
Subject: Re: Style question:  do vs do* and let vs. let*
Date: 
Message-ID: <cf333042.0306030939.139239ca@posting.google.com>
"Michael Greenberg" <··········@scr.siemens.com> wrote in message news:<·····················@iad-read.news.verio.net>...
> When you use a 'do' or 'let', which form do you use when there is no
> necessity to use one or the other.

When there is no semantic necessity for the * form, of course you use
the ordinary form. Why write something unnecessary?

> For example
> 
> (let ((v1 1)
>         (v2 2))
>  ...)
> 
> would you use let or let*.  Why?

1. So I don't have to hold down Shift and type 8.

2. So I don't have to waste the time of someone who will read the code
six months from now (could be myself) and who will instinctively
inspect all of the variable initializations in search of the
dependencies among them which are signaled by the *, only to discover
to his or her irritation that there are none!

> I was discussing this with a colleague today...I had been using 'let'.  He
> thought that let* was better.  His argument was that it is more important to
> highlight the need for parallel assignment rather then serial assignment
> because the former case is more difficult to recognize.

The only difference is that of scope. The expressions are evaluated in
lexical order in both cases. Under LET, the expressions do not see the
bindings; the bindings are established when the evaluation is done.
Under LET*, each binding is established right after the evaluation of
its initializing expression, so subsequent initializations can refer
to results of the previous initializations using the established
bindings.

There rarely occurs a specific need for parallel assignment. It
happens when you want to shadow some variables in an outer scope. For
example:

  (let (left right)
    ...
    (let ((left right)
          (right left))
       ;; right and left are swapped in this scope, so cannot use let*
       ))

The parallel binding allows the initializing expressions to refer to
the *outer* left and right to compute the values, and then the binding
pass establishes the inner left and right variables.

It would be a poor economy of expression to use LET* everywhere just
so you could use a LET to highlight the presence of this kind of rare
situation which critically depends on parallel binding. Such
situations are easily removable: choose non-shadowing names for
variables in the inner block! If you avoid such situations, then the
readers of your code don't have to suspect them when they see LET.

It's much more useful to use LET everywhere, and use LET* to signal
that there are dependencies among the initializing expressions. These
dependencies frequently arise in code, and are not removable by a
simple variable renaming.

Let's look at this another way. Suppose that there were three LET
constructs: ···@, LET and LET*. ···@ would be for the parallel case,
LET for the normal case, and LET* for the serial case. The normal case
LET would reject any expressions that refer to any of the symbols
which are bound, thereby signaling to the programmer that either ···@
or LET* must be chosen. Of course you would use the normal LET most of
the time, and let the error messages alert you to the need for one of
the others. But which one would be the most frequent resolution for
errors? It would almost certainly be LET*. It could be that 80% of the
forms end up being LET, 19% end up being LET* and 1% end up being
···@. So given that we have two symbols only, should you reserve one
for highlighting a 19% case or reserve the other for highlighting a 1%
case?

In the case of loops, the preference for DO over DO* is even more
clear. Parallel updates of the loop variables are by far the simpler
case to analyze and understand, because the *new* value of each
variable is computed from the *previous* iteration's value for that
variable or any other. Loops which use DO* in an essential way can be
a lot harder to understand; when the update expression refers to a
variable, it's no longer clear whether it's the old one or the new
one. These difficult loops need to be highlighted, so that the
reader's brain wakes up and makes itself alert and ready to do extra
work.

This is exactly how you reason about the correctness of programs when
you perform formal verification. When the program can modify
variables, in the proof you use some notation to represent the old
values. For example, in reasoning about the statement (incf x) we
might use x' to refer to the previous value of x. The postcondition of
the statement is then expressed by the equation ``x = x' + 1''. In the
theory, you grant yourself access to the old variable by way of a
special notation. The DO loop lets us practice the some of the
conveniences of the theory by giving us explicit access to the
``frozen'' old values.