[comp.lang.scheme] Internal definitions as a combination of LETREC's and LET*'s.

ramsdell@linus.UUCP (John D. Ramsdell) (10/31/88)

I would like to shift the current topic of this news group to an issue
of Scheme language design: the meaning of internal definitions.  I
contrast two interpretations of internal definitions:

	[1] internal definitions as LETREC's, and
	[2] internal definitions as a combination of LETREC's and LET*'s.

R3RS describes internal definitions in Section 5.2.2.  Some Scheme
implementations permit definitions to occur at the beginning of the
syntactic entity <body>, and are simply a syntactic variation of
LETREC.  In my opinion, they are an important variation as they reduce
the number of paratheses and make programs more readable.

Let me remind readers of the definition of LETREC of Section 7.3.  It
is equivalent to the following combinations of LET's and SET!'s:

(LETREC ((<var-0> <init-0>)
              ...
         (<var-n> <init-n>))
  <body>)
         ==>
(LET ((<var-0> <undefined>)
           ...
      (<var-n> <undefined>))
  (LET ((<temp-0> <init-0>)
              ...
        (<temp-n> <init-n>))
    (SET! <var-0> <init-0>)
            ...
    (SET! <var-n> <init-n>)
    <body>))

The second LET is there to ensure the property that the init
expressions are evaluated in an arbitrary order.  That is, no init
expression can depend of the value of any other one.  Thus the
following is incorrect.

(LAMBDA (X)
  (DEFINE A 4)
  (DEFINE B (* A A))
  (+ A (* X B)))

Yet at top level, it is okay to define values in terms of other
definitions.  An obvious way of making internal definitions behave
more like top level definitions, is to specify the order in which the
init bodies are evaluated.  I call this interpretation internal
definitions as a combination of LETREC's and LET*'s; a definition
becomes equivalent to the following combinations of LET's and SET!'s:

(LET ()
  (DEFINE <var-0> <init-0>)
            ...
  (DEFINE <var-n> <init-n>)
  <body>)
         ==>
(LET ((<var-0> <undefined>)
             ...
      (<var-n> <undefined>))
  (SET! <var-0> <init-0>)		; init's must be evaluated
          ...				; in the order presented.
  (SET! <var-n> <init-n>)
  <body>)

Aside from making internal definition behave more like top level
definitions, I think this meaning of internal definitions reduces the
number of parentheses, and makes programs more readable.  What's your
opinion? 
John

pierce@lanai.cs.ucla.edu (Brad Pierce) (11/01/88)

In article <41415@linus.UUCP> ramsdell@linus.UUCP (John D. Ramsdell) writes:
>Yet at top level, it is okay to define values in terms of other
>definitions.  An obvious way of making internal definitions behave
>more like top level definitions, is to specify the order in which the
>init bodies are evaluated.  I call this interpretation internal
>definitions as a combination of LETREC's and LET*'s; a definition
>becomes equivalent to the following combinations of LET's and SET!'s:
>
>(LET ()
>  (DEFINE <var-0> <init-0>)
>            ...
>  (DEFINE <var-n> <init-n>)
>  <body>)
>         ==>
>(LET ((<var-0> <undefined>)
>             ...
>      (<var-n> <undefined>))
>  (SET! <var-0> <init-0>)		; init's must be evaluated
>          ...				; in the order presented.
>  (SET! <var-n> <init-n>)
>  <body>)
>

Here's one possible problem, at least with the suggested expansion:


               (define x 5)

               (let ()
                 (define y x)
                 (define x 'any)
                 y)


Then wouldn't the result be unspecified, even though the intuitive
answer is 5? 

-- Brad Pierce


P.S. Something else I'm curious about...

Also, is one allowed to declare the same identifier more than once in the same
lambda closure in official Scheme? The Scheme I am currently using doesn't give
an error message when I try to do this:  ((lambda (x x) x) 1 2) 

And is it officially legal to "define" something more than once at top level.
The reason that I ask is that the expansion looks a little shaky in the case
that one would re"define" an identifier in such a clause.