The most general form of let/let* Marc Nieper-Wißkirchen (15 Nov 2022 12:30 UTC)
Re: The most general form of let/let* Lassi Kortela (15 Nov 2022 20:11 UTC)
Re: The most general form of let/let* Lassi Kortela (15 Nov 2022 20:23 UTC)
Re: The most general form of let/let* Marc Nieper-Wißkirchen (15 Nov 2022 20:28 UTC)
Re: The most general form of let/let* John Cowan (15 Nov 2022 20:38 UTC)
Re: The most general form of let/let* Marc Nieper-Wißkirchen (15 Nov 2022 20:48 UTC)
Re: The most general form of let/let* Daphne Preston-Kendal (15 Nov 2022 20:35 UTC)
Re: The most general form of let/let* Marc Nieper-Wißkirchen (15 Nov 2022 20:43 UTC)
Re: The most general form of let/let* Lassi Kortela (16 Nov 2022 08:19 UTC)
Re: The most general form of let/let* Jeremy Steward (17 Nov 2022 01:53 UTC)
Re: The most general form of let/let* Marc Nieper-Wißkirchen (17 Nov 2022 07:49 UTC)
Re: The most general form of let/let* Jeremy Steward (17 Nov 2022 02:11 UTC)
Re: The most general form of let/let* Marc Nieper-Wißkirchen (17 Nov 2022 07:55 UTC)
Re: The most general form of let/let* Lassi Kortela (17 Nov 2022 08:01 UTC)

The most general form of let/let* Marc Nieper-Wißkirchen 15 Nov 2022 12:30 UTC

In Scheme, we use the `let' construct when we want our interpreter to
perform several independent operations, and we are interested in the
return values of these operations.

If, on the other hand, the operations depend on the results (let us
neglect side effects, which also create dependencies) of previous
operations, we use the `let*' construct.

Often, however, the most abstract representation of the algorithm we
want to code would need a mixture of `let' and `let*' forms.  Consider
the following example:

(let* ((a (f))
        (b (g))
        (c (h b))
        (d (k c)))
  <body>)

Here, D depends on C, which depends on B.  So

(let ((a (f))
       (b (g)))
  (let* ((c (h b))
          (d (k c)))
    <body>))

is a rewrite that is closer to the actual dependency graph.  But it is
still not an accurate image of the platonic idea.  In particular,

(let ((b (g)))
  (let* ((c (h b))
          (d (k c)))
    (let ((a (f)))
      <body>)))

is a different approximation, which like the other two, still does not
capture the idea that the binding to A is independent of the other
bindings.

So, a way to express a general dependency graph is needed and let the
Scheme interpreter sort out a suitable sequencing.

I propose a form like the following one:

(let-values (((d) (using c
                            (k c)))
                   ((a) (f))
                   ((c) (using b
                            (h b)))
                   ((b) (g)))
  <expr>)

Marc

“The purpose of abstracting is not to be vague, but to create a new
semantic level in which one can be absolutely precise.”
― Edsger W. Dijkstra