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)
|
I file improvements like this to let under ‘things we’d do differently if we did Scheme again from scratch, but it’s too late now’. Personally I’d have three forms: let (which would be what we currently call letrec*), recur (which would be what we currently call named let), and let-syntax (which would be what we currently call letrec-syntax). The explosion of near-identical let forms, and the need to nest them sometimes, is a wart, but adding more just creates an xkcd 927 situation. Daphne > On 15 Nov 2022, at 13:30, Marc Nieper-Wißkirchen <xxxxxx@nieper-wisskirchen.de> wrote: > > 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