• Re: Scheme is not another C-like language? was Compilers :)

    From Nils M Holm@21:1/5 to Kaz Kylheku on Thu Jan 12 11:15:25 2023
    Kaz Kylheku <864-117-4973@kylheku.com> wrote:
    I tried (lambda () (define x 42) (define x 43)) in a Scheme
    implementation and got an error about the duplicate variable.

    That's completely silly since it breaks the idea that the block scoped
    define can just be desugared to nested lets.

    If I am not completely mistaken, local DEFINE expands to LETREC
    and not to nested LET, so your example would result in two
    instances of X in the same scope:

    (lambda ()
    (letrec ((x 42)
    (x 43))))

    --
    Nils M Holm < n m h @ t 3 x . o r g > http://t3x.org
    [See the more complete analysis just posted. -John]

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From George Neuner@21:1/5 to 864-117-4973@kylheku.com on Thu Jan 12 02:54:37 2023
    On Wed, 11 Jan 2023 11:02:56 -0000 (UTC), Kaz Kylheku <864-117-4973@kylheku.com> wrote:


    It seems that Scheme, with its ugly (define ...) that can be used inside >block scopes, [disallows name redefinition]!

    Agree it's ugly: I never use internal defines in my own code.
    Unfortunately some people love them.


    I tried (lambda () (define x 42) (define x 43)) in a Scheme
    implementation and got an error about the duplicate variable.

    That's completely silly since it breaks the idea that the block scoped
    define can just be desugared to nested lets.


    Unfortunately the experience varies by version:


    From R3RS to R5RS, a series of internal defines is treated AS IF they
    all are part of a single 'letrec' with the scope being the whole body. 'letrec', of course, does not permit multiple bindings to the same
    name.

    In R6RS and R7RS, a series of internal defines is treated as a
    'letrec*' [note trailing *]. letrec* is equivalent to nested letrec
    and so does permit rebinding to the same name ... which will shadow
    any previous bindings.



    from R5RS 5.2.2 Internal Definitions

    ... The variable defined by an internal defnition is local to the
    body. That is, variable is bound rather than assigned, and the region
    of the binding is the entire body. For example,

    (let ((x 5))
    (define foo (lambda (y) (bar x y)))
    (define bar (lambda (a b) (+ (* a b) a)))
    (foo (+ x 3))) => 45

    A body containing internal definitions can always be converted into a completely equivalent letrec expression. For example, the let
    expression in the above example is equivalent to

    (let ((x 5))
    (letrec ((foo (lambda (y) (bar x y)))
    (bar (lambda (a b) (+ (* a b) a))))
    (foo (+ x 3))))

    Just as for the equivalent letrec expression, it must be possible to
    evaluate each expression of every internal definition in a body
    without assigning or referring to the value of any variable being
    defined.



    From R6RS 11.3 Bodies

    The <body> of a lambda, let, let*, let-values, let*-values, letrec, or
    letrec* expression, or that of a definition with a body consists of
    zero or more definitions followed by one or more expressions.

    <definition> ... <expression1> <expression2> ...

    Each identifier defined by a definition is local to the <body>. That
    is, the identifier is bound, and the region of the binding is the
    entire <body> (see section [5.2]).

    Example:

    (let ((x 5))
      (define foo (lambda (y) (bar x y)))   (define bar (lambda (a b) (+ (* a b) a)))   (foo (+ x 3)))               =>  45

    When begin, let-syntax, or letrec-syntax forms occur in a body prior
    to the first expression, they are spliced into the body; see
    section [11.4.7]. Some or all of the body, including portions wrapped
    in begin, let-syntax, or letrec-syntax forms, may be specified by a
    macro use (see section [9.2]).

    An expanded <body> (see chapter [10]) containing variable definitions
    can always be converted into an equivalent letrec* expression. For
    example, the let expression in the above example is equivalent to

    (let ((x 5))
      (letrec* ((foo (lambda (y) (bar x y)))             (bar (lambda (a b) (+ (\* a b) a))))     (foo (+ x 3))))

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)