Re: [racket-dev] internal-definition parsing
Another attempt at this old thing -- the idea of having some internal
`#%begin' thing (see ancient context below):
`begin' is something that is not only a ";" because of how it
sequences things, it's also a "return" thing -- it can be read as
(begin x ... y) ~ { x; ...; return y; }. So maybe a `#%begin' should
take its context from its last expression?
It looks to me like this could be a similar case to `#%app' usually
doing the right thing, and easy to resolve when it isn't, as in
converting a macro like
(define-syntax-rule (noisy x ...)
(begin (displayln 'start) x ... (displayln 'start)))
to:
(define-syntax-rule (noisy x ...)
(begin (displayln 'start) (begin x ...) (displayln 'start)))
On July 7th 2010, Matthew Flatt wrote:
>
> An Implicit Internal-Definitions Form
> -
>
> Many forms --- including `lambda' `let', and the function-shorthand
> variant of `define' --- support internal definitions. The handling
> of internal definitions is currently tired to the form.
>
> An alternative would be to have those forms implicitly wrap a group
> of internal-definition forms with `#%body', in much the same way
> that an application form is converted to a use of `#%app'. Then, the
> treatment of internal definitions could be independently configured
> through a module import. For example, one module might use a
> `#%body' that corresponds to the old handling of internal
> definitions, while another module could import a `#%body' that
> corresponds to the new handling.
>
> Setting aside the backward-compatibility issues of adding an
> implicit form, I think it turns out not to work as well as
> `#%app'. The problem is that there's not a good place to get the
> lexical context to use for the implicit `#%body'. We have many
> macros analogous to
>
> (define-syntax-rule (squawk body ...)
>(begin
> (displayln "squawk!")
> (let () body ...)))
>
> If you take the lexical context from the parentheses that surround
> the `let' form, then the `#%body' is drawn from the context of the
> `squawk' definition, while the intent was more likely to get it from
> the use of `squawk'. Meanwhile, the `body ...' sequence itself
> doesn't necessarily have a lexical context (since it doesn't have a
> parenthesis, roughly), and the sequence is recreated by the macro
> implementation anyway.
>
> This problem happens occasionally with `#%app'. When a use of
> identifier macro expands in an application position, for example,
> the implementor of the identifier macro usually should copy the
> lexical context of the old application form to the expansion
> result. Such cases are more rare than examples like `squawk',
> though.
>
> So, an implicit `#%body' form seems like a good idea in principle,
> but it doesn't seem to work out well with our current syntax. I'm
> currently inclined to not change Racket and to treat this as
> something to support better the next time we define a core syntax,
> but I'm interested in further discussion.
--
((lambda (x) (x x)) (lambda (x) (x x))) Eli Barzilay:
http://barzilay.org/ Maze is Life!
_
Racket Developers list:
http://lists.racket-lang.org/dev
Re: [racket-dev] internal-definition parsing
On Wed, Oct 13, 2010 at 7:08 AM, Carl Eastlund wrote: > In the case I have, though, I want the sequence to be empty. The > problem is that these bodies -- (let () ...), (parameterize () ...), > etc. -- are used for a lot of different things. A macro may splice in > a sequence that is intended to represent definitions to bind in a > scope, expressions to evaluate for effect, expressions to evaluate in > order and return the last, mixed definitions and expressions, or > perhaps some other odd interpretation of the body sequence. This is the reason that I prefer a lot of lattitude in Scheme syntax. There are forms that no human would write but that are marginally legitimate and might be generated by a macro. It is painful to try to make every part of a complex macro expand into well-written code. -- ~jrm _ For list-related administrative tasks: http://lists.racket-lang.org/listinfo/dev
Re: [racket-dev] internal-definition parsing
In the case I have, though, I want the sequence to be empty. The problem is that these bodies -- (let () ...), (parameterize () ...), etc. -- are used for a lot of different things. A macro may splice in a sequence that is intended to represent definitions to bind in a scope, expressions to evaluate for effect, expressions to evaluate in order and return the last, mixed definitions and expressions, or perhaps some other odd interpretation of the body sequence. I have some RackUnit test cases that are currently empty as I have no checks to put in them. They're just placeholders. Under the planet-based SchemeUnit, this works fine. Under RackUnit, it expands into (parameterize ([stuff ...])), because there are no body expressions. This happens about 2-3 macros down from where I write it. We could start adding "blame" and possibly making various macros add (block e ...), but really, why not just make it work? It seems a lot easier, and all it means is that you get in trouble if you forget to write the body of your function. That's not really that surprising an error. The (define (f) ... (define (g) ...)) bug Matthew originally cited is fairly easy to debug, too. Running into a problem with nested macros imported from someone else's libraries is something I'd much rather make easy. Carl Eastlund On Wed, Oct 13, 2010 at 10:02 AM, Matthias Felleisen wrote: > > In a sense you just want to change the 'fault blame' designation when > > e/d ... > > moves from macro foo to macro bar so that bar isn't blamed. It is then > foo's job to ensure that the sequence isn't empty and foo is blamed when > things go wrong. > > I suspect this can be solved in syntax-parse, too. > > -- Matthias > > > > On Oct 13, 2010, at 8:34 AM, Matthew Flatt wrote: > >> At Wed, 13 Oct 2010 08:23:09 -0400, Carl Eastlund wrote: >>> On Wed, Jul 7, 2010 at 12:23 PM, Matthew Flatt wrote: Should an expression be required at the end? A `module', `unit', or `class' body can consist of just definitions. Similarly, if an internal-definition context ends with a definition, we could define the result to be `(void)', which is what the `block' form does. I think it's better to require an expression at the end, partly on the grounds that the internal-definition block is supposed to return a value (unlike the body of `module', etc.) and partly to avoid making forms like (define (f x) x (define (g y) y)) legal when they are almost certainly mistakes. >>> >>> Macros constructing sequences of def-or-expr for implicit begin (as >>> found in let, lambda, parameterize, etc.) won't always know if the >>> sequence is empty or non-empty, and whether it is terminated by an >>> expression or definition. If a begin-like sequence ends with a >>> definition, currently a macro must add an expression such as (void) to >>> follow it. If it ends with an expression, the macro must *not* add >>> such an expression, because that changes the return value. It would >>> be far more convenient if primitive forms worked with any sequence of >>> def-or-expr so that each wrapper macro did not have to implement its >>> own local-expand loop to figure out how the sequence ends, and as >>> always it is much nicer to write macros when sequences can be >>> zero-length. >> >> How about the option of using `block' in the macro implementation, >> instead of allowing forms like `(let ())', `(define (h))', the `f' and >> `g' example above? _ For list-related administrative tasks: http://lists.racket-lang.org/listinfo/dev
Re: [racket-dev] internal-definition parsing
In a sense you just want to change the 'fault blame' designation when e/d ... moves from macro foo to macro bar so that bar isn't blamed. It is then foo's job to ensure that the sequence isn't empty and foo is blamed when things go wrong. I suspect this can be solved in syntax-parse, too. -- Matthias On Oct 13, 2010, at 8:34 AM, Matthew Flatt wrote: > At Wed, 13 Oct 2010 08:23:09 -0400, Carl Eastlund wrote: >> On Wed, Jul 7, 2010 at 12:23 PM, Matthew Flatt wrote: >>> Should an expression be required at the end? A `module', `unit', or >>> `class' body can consist of just definitions. Similarly, if an >>> internal-definition context ends with a definition, we could define the >>> result to be `(void)', which is what the `block' form does. >>> >>> I think it's better to require an expression at the end, partly on the >>> grounds that the internal-definition block is supposed to return a >>> value (unlike the body of `module', etc.) and partly to avoid making >>> forms like >>> >>> (define (f x) >>> x >>> (define (g y) >>> y)) >>> >>> legal when they are almost certainly mistakes. >> >> Macros constructing sequences of def-or-expr for implicit begin (as >> found in let, lambda, parameterize, etc.) won't always know if the >> sequence is empty or non-empty, and whether it is terminated by an >> expression or definition. If a begin-like sequence ends with a >> definition, currently a macro must add an expression such as (void) to >> follow it. If it ends with an expression, the macro must *not* add >> such an expression, because that changes the return value. It would >> be far more convenient if primitive forms worked with any sequence of >> def-or-expr so that each wrapper macro did not have to implement its >> own local-expand loop to figure out how the sequence ends, and as >> always it is much nicer to write macros when sequences can be >> zero-length. > > How about the option of using `block' in the macro implementation, > instead of allowing forms like `(let ())', `(define (h))', the `f' and > `g' example above? > > _ > For list-related administrative tasks: > http://lists.racket-lang.org/listinfo/dev _ For list-related administrative tasks: http://lists.racket-lang.org/listinfo/dev
Re: [racket-dev] internal-definition parsing
At Wed, 13 Oct 2010 08:23:09 -0400, Carl Eastlund wrote: > On Wed, Jul 7, 2010 at 12:23 PM, Matthew Flatt wrote: > > Should an expression be required at the end? A `module', `unit', or > > `class' body can consist of just definitions. Similarly, if an > > internal-definition context ends with a definition, we could define the > > result to be `(void)', which is what the `block' form does. > > > > I think it's better to require an expression at the end, partly on the > > grounds that the internal-definition block is supposed to return a > > value (unlike the body of `module', etc.) and partly to avoid making > > forms like > > > > (define (f x) > > x > > (define (g y) > > y)) > > > > legal when they are almost certainly mistakes. > > Macros constructing sequences of def-or-expr for implicit begin (as > found in let, lambda, parameterize, etc.) won't always know if the > sequence is empty or non-empty, and whether it is terminated by an > expression or definition. If a begin-like sequence ends with a > definition, currently a macro must add an expression such as (void) to > follow it. If it ends with an expression, the macro must *not* add > such an expression, because that changes the return value. It would > be far more convenient if primitive forms worked with any sequence of > def-or-expr so that each wrapper macro did not have to implement its > own local-expand loop to figure out how the sequence ends, and as > always it is much nicer to write macros when sequences can be > zero-length. How about the option of using `block' in the macro implementation, instead of allowing forms like `(let ())', `(define (h))', the `f' and `g' example above? _ For list-related administrative tasks: http://lists.racket-lang.org/listinfo/dev
Re: [racket-dev] internal-definition parsing
On Wed, Jul 7, 2010 at 12:23 PM, Matthew Flatt wrote: > Should an expression be required at the end? A `module', `unit', or > `class' body can consist of just definitions. Similarly, if an > internal-definition context ends with a definition, we could define the > result to be `(void)', which is what the `block' form does. > > I think it's better to require an expression at the end, partly on the > grounds that the internal-definition block is supposed to return a > value (unlike the body of `module', etc.) and partly to avoid making > forms like > > (define (f x) > x > (define (g y) > y)) > > legal when they are almost certainly mistakes. Macros constructing sequences of def-or-expr for implicit begin (as found in let, lambda, parameterize, etc.) won't always know if the sequence is empty or non-empty, and whether it is terminated by an expression or definition. If a begin-like sequence ends with a definition, currently a macro must add an expression such as (void) to follow it. If it ends with an expression, the macro must *not* add such an expression, because that changes the return value. It would be far more convenient if primitive forms worked with any sequence of def-or-expr so that each wrapper macro did not have to implement its own local-expand loop to figure out how the sequence ends, and as always it is much nicer to write macros when sequences can be zero-length. --Carl _ For list-related administrative tasks: http://lists.racket-lang.org/listinfo/dev
Re: [racket-dev] internal-definition parsing
On Jul 8, Matthias Felleisen wrote: > On Jul 8, 2010, at 12:09 PM, Jay McCarthy wrote: > > > #%module-begin as the top level controlling macro is a distinguishing > > feature. Requires and provides can only be there and you know there's > > only one application. > > These could be an argument to the #%...-begin macro: > > are-you-top-level? :: (U false (interface Provides Requires)) (It could also be an argument for making local requires more accessible...) -- ((lambda (x) (x x)) (lambda (x) (x x))) Eli Barzilay: http://barzilay.org/ Maze is Life! _ For list-related administrative tasks: http://lists.racket-lang.org/listinfo/dev
Re: [racket-dev] internal-definition parsing
On Jul 8, Matthias Felleisen wrote: > > 2. I do not understand why #%body isn't enough. Couldn't #%body >locally expand to the point where defs and exps are >distinguished? Yes, it could -- and I guess that would be in analogy to `#%module-begin'. But I generally don't like that macros that need to distinguish definitions from expressions need to do that work in that context too -- it's delicate enough that it shouldn't be left to the "good enough" instinct of leaving partial solutions. (In the `#%module-begin' case, a common result of this instinct is matching on expressions that use `define', without expanding them, or expanding them without dealing with macros.) > 3. Also, I am beginning to wonder whether the right name is >#%block-begin of #%body-begin > > 4. The next thing to consider is whether #%module-begin and >#%block-begin are truly separate features. In a sense, we now >should say that modules are just bodies. Or is there a >difference? It could be the same macro with (syntax-local-context) distinguishing the two... It might even make sense to do so in some cases where a similar macro is needed in both (as with the lazy case). -- ((lambda (x) (x x)) (lambda (x) (x x))) Eli Barzilay: http://barzilay.org/ Maze is Life! _ For list-related administrative tasks: http://lists.racket-lang.org/listinfo/dev
Re: [racket-dev] internal-definition parsing
On Jul 8, 2010, at 12:09 PM, Jay McCarthy wrote: > #%module-begin as the top level controlling macro is a distinguishing > feature. Requires and provides can only be there and you know there's > only one application. These could be an argument to the #%...-begin macro: are-you-top-level? :: (U false (interface Provides Requires)) -- Matthias _ For list-related administrative tasks: http://lists.racket-lang.org/listinfo/dev
Re: [racket-dev] internal-definition parsing
On Thu, Jul 8, 2010 at 11:19 AM, Matthias Felleisen wrote: > > On Jul 7, 2010, at 5:55 PM, Eli Barzilay wrote: > >> Some examples that show how useful this is: >> >> * In the lazy language you want the implicit begin to force all >> expressions except for the last one. >> >> * I've redefined the implicit begin (in an ugly way) for my course >> language to force all non-tail expressions to have a `Void' type. >> >> * The scribble/text language should really return a list of all >> values instead of just the last one. It currently provides `text' >> that builds on `begin/collect', which allows each block of >> consecutive definitions to be mutually recursive -- this is now a >> problem in that it's different in a subtle way than the default >> implicit begin. >> >> I think that a good goal is to have all of these uses available as >> simple macro definitions. >> >> If you take the lazy use as an example, then just a single `#%body' >> thing is not enough: since it needs to force only expressions, then >> having a `#%body' means that it will need to do its own crawling over >> the expressions to find which ones are not definitions and force >> them. So it looks like another special #% macro would be needed, and >> even that is not enough to implement the last one conveniently, since >> it needs to collect all non-definition expressions and combine them. > > > 1. Three distinct examples (plus Algol, which could benefit too) sound like > enough. > > 2. I do not understand why #%body isn't enough. Couldn't #%body locally > expand to the point where defs and exps are distinguished? > > 3. Also, I am beginning to wonder whether the right name is #%block-begin of > #%body-begin > > 4. The next thing to consider is whether #%module-begin and #%block-begin are > truly separate features. In a sense, we now should say that modules are just > bodies. Or is there a difference? #%module-begin as the top level controlling macro is a distinguishing feature. Requires and provides can only be there and you know there's only one application. Jay -- Jay McCarthy Assistant Professor / Brigham Young University http://teammccarthy.org/jay "The glory of God is Intelligence" - D&C 93 _ For list-related administrative tasks: http://lists.racket-lang.org/listinfo/dev
Re: [racket-dev] internal-definition parsing
On Jul 7, 2010, at 5:55 PM, Eli Barzilay wrote: > Some examples that show how useful this is: > > * In the lazy language you want the implicit begin to force all >expressions except for the last one. > > * I've redefined the implicit begin (in an ugly way) for my course >language to force all non-tail expressions to have a `Void' type. > > * The scribble/text language should really return a list of all >values instead of just the last one. It currently provides `text' >that builds on `begin/collect', which allows each block of >consecutive definitions to be mutually recursive -- this is now a >problem in that it's different in a subtle way than the default >implicit begin. > > I think that a good goal is to have all of these uses available as > simple macro definitions. > > If you take the lazy use as an example, then just a single `#%body' > thing is not enough: since it needs to force only expressions, then > having a `#%body' means that it will need to do its own crawling over > the expressions to find which ones are not definitions and force > them. So it looks like another special #% macro would be needed, and > even that is not enough to implement the last one conveniently, since > it needs to collect all non-definition expressions and combine them. 1. Three distinct examples (plus Algol, which could benefit too) sound like enough. 2. I do not understand why #%body isn't enough. Couldn't #%body locally expand to the point where defs and exps are distinguished? 3. Also, I am beginning to wonder whether the right name is #%block-begin of #%body-begin 4. The next thing to consider is whether #%module-begin and #%block-begin are truly separate features. In a sense, we now should say that modules are just bodies. Or is there a difference? -- Matthias _ For list-related administrative tasks: http://lists.racket-lang.org/listinfo/dev
Re: [racket-dev] internal-definition parsing
On Jul 7, Matthew Flatt wrote: > Short version: > > I'm planning to change internal-definition expansion (anywhere that > says `body ...' in the Racket documentation) to allow expressions to > mingle with definitions. For example, > [...] Nice! On Jul 7, Matthias Felleisen wrote: > > 4. I am vaguely interested in #%body because I have a hunch that >there are yet more possibilities. But at the same time, I >understand your objection and I can only see a limited utility of >#%body now. (That doesn't mean much, because I originally failed >to appreciate #%module-begin.) I have a very conceret interest in that. Is there any concrete example for something that would go wrong with it now? What bugs me often is that playing around with a different semantics for body sequences is currently very tedious -- I have to redefine `lambda', `let', `define', and their (many) relatives (even things like `for' etc, if it should be complete), and in practice it always ends up being a half-assed job instead... Some examples that show how useful this is: * In the lazy language you want the implicit begin to force all expressions except for the last one. * I've redefined the implicit begin (in an ugly way) for my course language to force all non-tail expressions to have a `Void' type. * The scribble/text language should really return a list of all values instead of just the last one. It currently provides `text' that builds on `begin/collect', which allows each block of consecutive definitions to be mutually recursive -- this is now a problem in that it's different in a subtle way than the default implicit begin. I think that a good goal is to have all of these uses available as simple macro definitions. If you take the lazy use as an example, then just a single `#%body' thing is not enough: since it needs to force only expressions, then having a `#%body' means that it will need to do its own crawling over the expressions to find which ones are not definitions and force them. So it looks like another special #% macro would be needed, and even that is not enough to implement the last one conveniently, since it needs to collect all non-definition expressions and combine them. -- ((lambda (x) (x x)) (lambda (x) (x x))) Eli Barzilay: http://barzilay.org/ Maze is Life! _ For list-related administrative tasks: http://lists.racket-lang.org/listinfo/dev
Re: [racket-dev] internal-definition parsing
At Wed, 7 Jul 2010 13:13:31 -0400, Matthias Felleisen wrote: > > 1. My most important concern is that begin-with-definitions takes Nx times > more time to expand than the current body expander. Are you going to use this > macro or are you going to bake it all into the implementation? The latter, so there's no slowdown. > 2. My second one is one of internal interest. In principle all 'body' forms > should be expanded in one single place and this should be a single point of > change here. Is this correct? Yes. _ For list-related administrative tasks: http://lists.racket-lang.org/listinfo/dev
Re: [racket-dev] internal-definition parsing
1. My most important concern is that begin-with-definitions takes Nx times more time to expand than the current body expander. Are you going to use this macro or are you going to bake it all into the implementation? 2. My second one is one of internal interest. In principle all 'body' forms should be expanded in one single place and this should be a single point of change here. Is this correct? 3. Historically our original form borrowed from Algol. I don't think Chez had this liberal notion. 4. I am vaguely interested in #%body because I have a hunch that there are yet more possibilities. But at the same time, I understand your objection and I can only see a limited utility of #%body now. (That doesn't mean much, because I originally failed to appreciate #%module-begin.) -- Matthias On Jul 7, 2010, at 12:23 PM, Matthew Flatt wrote: > Short version: > > I'm planning to change internal-definition expansion (anywhere that > says `body ...' in the Racket documentation) to allow expressions to > mingle with definitions. For example, > > (let () >(define (f) x) >(displayln f) >(define x 1) >(list f x)) > > would be allowed; the `displayln' call would print `#', > and the result would be a list containing the function `f' and the > number 1. > > Some other changes related to internal-definitions have been suggested, > but I don't plan to implement them for now. > > > > Long version: > > Mixing Expressions and Definitions > -- > > Long ago, internal-definition positions in MzScheme allowed multiple > sets of definitions separated by expressions. For example, > > (let () > (define x 1) > (display x) > (define y 2) > (display y)) > > was allowed. In that old mode, the definition of `y' started a new > group of definitions, so the right-hand side of `(define x ...)' could > not refer to `y'. In other words, the above was equivalent to > > (letrec ([x 1]) > (display x) > (letrec ([y 2]) > (display y))) > > I think this behavior mimicked Chez Scheme at the time, but I may be > mistaken. For whatever reason (I don't remember), we changed > internal-definition positions to now allow additional definitions after > an expression. Maybe it was to more closely match R5RS. > > > Meanwhile, `unit', `module', `class' and other forms evolved to allow > expressions mixed with definitions. Probably as a result, many have > suggested that internal definitions similarly allow expressions mixed > with definitions --- without the old grouping. In that case, the `let' > above would be equivalent to > > (letrec-values ([(x) 1] > [() (begin (display x) (values))] > [(y) 2]) > (display y)) > > This change seems like a good idea. Now that I've finally gotten around > to trying it out, I think we should go with it immediately. > > > Should an expression be required at the end? A `module', `unit', or > `class' body can consist of just definitions. Similarly, if an > internal-definition context ends with a definition, we could define the > result to be `(void)', which is what the `block' form does. > > I think it's better to require an expression at the end, partly on the > grounds that the internal-definition block is supposed to return a > value (unlike the body of `module', etc.) and partly to avoid making > forms like > > (define (f x) > x > (define (g y) > y)) > > legal when they are almost certainly mistakes. > > This change could be implemented in new `lambda', etc. bindings, but I > think existing forms in `racket' should change. Furthermore, to keep > things simple, the existing `scheme' forms --- most of which are the > same binding as the `racket' forms --- should also change. > > The change should not affect the `r5rs' language, and we should change > the `r6rs' language so that it doesn't inherit the more liberal > handling of internal-definition forms. > > There are no issues with backward-compatibility for existing `scheme' > and `racket' modules, as far as I can tell. The change would just > accept more modules. > > > More Internal-Definition Contexts > - > > Internal definitions could be allowed in more places, such as > > (define f > (define x 2) > x) > > In principle, where a single expression is expected, definitions could > be allowed to precede the expression. > > It's a tempting generalization, but probably too confusing. I think > it's better to use some form that groups definitions with an > expression: `(let () )', `(block )', or something like that. > > > An Implicit Internal-Definitions Form > - > > Many forms --- including `lambda' `let', and the function-shorthand > variant of `define' --- support internal definitions. The handling of > internal definitions is currently tired to the form. > > An alternative would be to have those forms impli
Re: [racket-dev] internal-definition parsing
Yeah! (And I think you're right about not having an implicit #%body, but I don't really know for sure.) Robby On Wed, Jul 7, 2010 at 11:23 AM, Matthew Flatt wrote: > Short version: > > I'm planning to change internal-definition expansion (anywhere that > says `body ...' in the Racket documentation) to allow expressions to > mingle with definitions. For example, > > (let () > (define (f) x) > (displayln f) > (define x 1) > (list f x)) > > would be allowed; the `displayln' call would print `#', > and the result would be a list containing the function `f' and the > number 1. > > Some other changes related to internal-definitions have been suggested, > but I don't plan to implement them for now. > > > > Long version: > > Mixing Expressions and Definitions > -- > > Long ago, internal-definition positions in MzScheme allowed multiple > sets of definitions separated by expressions. For example, > > (let () > (define x 1) > (display x) > (define y 2) > (display y)) > > was allowed. In that old mode, the definition of `y' started a new > group of definitions, so the right-hand side of `(define x ...)' could > not refer to `y'. In other words, the above was equivalent to > > (letrec ([x 1]) > (display x) > (letrec ([y 2]) > (display y))) > > I think this behavior mimicked Chez Scheme at the time, but I may be > mistaken. For whatever reason (I don't remember), we changed > internal-definition positions to now allow additional definitions after > an expression. Maybe it was to more closely match R5RS. > > > Meanwhile, `unit', `module', `class' and other forms evolved to allow > expressions mixed with definitions. Probably as a result, many have > suggested that internal definitions similarly allow expressions mixed > with definitions --- without the old grouping. In that case, the `let' > above would be equivalent to > > (letrec-values ([(x) 1] > [() (begin (display x) (values))] > [(y) 2]) > (display y)) > > This change seems like a good idea. Now that I've finally gotten around > to trying it out, I think we should go with it immediately. > > > Should an expression be required at the end? A `module', `unit', or > `class' body can consist of just definitions. Similarly, if an > internal-definition context ends with a definition, we could define the > result to be `(void)', which is what the `block' form does. > > I think it's better to require an expression at the end, partly on the > grounds that the internal-definition block is supposed to return a > value (unlike the body of `module', etc.) and partly to avoid making > forms like > > (define (f x) > x > (define (g y) > y)) > > legal when they are almost certainly mistakes. > > This change could be implemented in new `lambda', etc. bindings, but I > think existing forms in `racket' should change. Furthermore, to keep > things simple, the existing `scheme' forms --- most of which are the > same binding as the `racket' forms --- should also change. > > The change should not affect the `r5rs' language, and we should change > the `r6rs' language so that it doesn't inherit the more liberal > handling of internal-definition forms. > > There are no issues with backward-compatibility for existing `scheme' > and `racket' modules, as far as I can tell. The change would just > accept more modules. > > > More Internal-Definition Contexts > - > > Internal definitions could be allowed in more places, such as > > (define f > (define x 2) > x) > > In principle, where a single expression is expected, definitions could > be allowed to precede the expression. > > It's a tempting generalization, but probably too confusing. I think > it's better to use some form that groups definitions with an > expression: `(let () )', `(block )', or something like that. > > > An Implicit Internal-Definitions Form > - > > Many forms --- including `lambda' `let', and the function-shorthand > variant of `define' --- support internal definitions. The handling of > internal definitions is currently tired to the form. > > An alternative would be to have those forms implicitly wrap a group of > internal-definition forms with `#%body', in much the same way that an > application form is converted to a use of `#%app'. Then, the treatment > of internal definitions could be independently configured through a > module import. For example, one module might use a `#%body' that > corresponds to the old handling of internal definitions, while another > module could import a `#%body' that corresponds to the new handling. > > Setting aside the backward-compatibility issues of adding an implicit > form, I think it turns out not to work as well as `#%app'. The problem > is that there's not a good place to get the lexical context to use for > the implicit `#%body'. We have many macros analogous

