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.