Thank you for your valuable comments and putting this into a historical
context, Chris.

Am Di., 23. Jan. 2024 um 01:10 Uhr schrieb Chris Hanson <
c...@chris-hanson.org>:

> On 1/22/24 02:06, Marc Nieper-Wißkirchen wrote:> More and more, I have
> come to the conclusion that the
> > addition of the local defines to Scheme added a wart to the language
> > long ago.
> Speaking for GJS and Hal, I'll point out that the reason for local
> defines is pedagogical.  The similarity between top-level and local
> defines makes it easy for students to grasp the concept without having
> to explain yet another binding mechanism.  And since LETREC didn't exist
> at that time, it was a sensible choice.
>
> I'd argue that it's still valuable.  It's also something that both GJS
> and I use regularly and I generally find preferable to LETREC.
>

I also use them regularly (primarily for internal procedure definitions),
and I don't mean to say they are useless.  For most warts in a programming
language, there was a good reason to introduce it.  My point is that there
should be a better way to achieve what internal defines achieve without
making the Scheme language more complicated.  For example, a simpler syntax
for `letrec' when specialized to procedures would already help.  With the
current tools,

(lambda ()
  (define (f) 1)
  (define (g) 2)
  (define (h) (+ (f) (g)))
  (h))

would have to be replaced by

(lambda ()
  (letrec ((f (lambda () 1))
           (g (lambda () 2))
           (h (lambda () (+ (f) (g))))
    (h)))

which has more boilerplate and has inferior indentation behaviour (for
longer or more complicated procedures).

A better (but not yet optimal) tool could be something like a, say,
`labels' macro, e.g. as in:

(lambda ()
  (labels
      ((f) 1)
      ((g) 2)
      ((h) (+ (f) (g)))
    (h)))

I also don't find the argument about continuation behavior particularly
> compelling.  I have been using internal definitions for 40 years without
> once running into an issue with it; although admittedly I rarely use
> internal definitions for anything other than procedure definitions.  It
> might be simpler to restrict what kinds of values can be used in those
> definitions than worrying about reused continuations.
>

Internal defines, as specified in R[4567]RS, have no more problems with
continuations than `letrec' does.  Questionable behaviour shows up when
local definitions are added after expressions because these can alter the
semantics of the earlier expressions.  SRFI 245's deviation from R6RS
program body semantics was an attempt to fix this, but it doesn't.

I don't mean the continuation behaviour when saying that local defines may
constitute a wart in the language.  One of the selling points of the Scheme
language is its simplicity, in particular, that it doesn't have to
distinguish between statements and expressions.  Everything is an
expression.  With local definitions, however, we now have to distinguish
between expressions and definitions.  This complicates reasoning about and
writing macros (not a problem in R4RS); see what Racket all had to add in
functionality to give macro writers sufficient power.  We wouldn't have to
discuss topics like splicing or non-splicing behaviour or where bodies
instead of expressions may appear if there weren't local defines.

Marc

Reply via email to