I've implemented (not yet pushed) a revision of internal-definition expansion. The `quicksort!' functions at the start of this thread (see http://lists.racket-lang.org/dev/archive/2011-May/006547.html) run the same with that change.
Definitions are partitioned into minimal sets that satisfy the following rule: if a definition's binding is referenced (after all macro expansion) by an earlier definition, the two definitions and all in between are in the same set. If a set contains a single definition that does not refer to itself, then it's a `let' layer, otherwise the group is a `letrec' layer. Actually, I didn't change internal-definition expansion. I changed `letrec-syntaxes+values' while leaving `letrec' along. That is, (letrec-syntaxes+values () clauses body ...) is not necessarily the same as (letrec clauses body ...) Making them different is a little awkward, but it solves a problem with `local-expand': At Fri, 20 May 2011 09:28:40 -0700, Matthew Flatt wrote: > At Fri, 20 May 2011 11:03:04 -0400, Sam Tobin-Hochstadt wrote: > > On Fri, May 20, 2011 at 10:53 AM, Matthew Flatt <mfl...@cs.utah.edu> wrote: > > > I like the idea of adjusting the semantics of internal definitions and > > > leaving `letrec' alone. > > > > While this seems like a nice change, how does it interact with > > internal syntax definitions? If there are internal syntax > > definitions, do we fall back to `letrec-syntaxes+values'? > > Good question. Yes, I think an internal syntax definition would have to > be treated like a definition that refers to the last binding in the set > of definitions. No, it's no good to "give up" when variable definitions are mixed with syntax definitions. For example (and possibly what Sam was thinking of), internal-definition positions that have Typed Racket declarations correspond to mixtures of variable and syntax definitions. We certainly want an improvement of internal definitions to work in Typed Racket. For fully expanded programs, mixing variable and syntax definitions causes no trouble. The problem is with `local-expand', which is supposed to preserve `letrec-syntaxes+values' in an expansion, and Typed Racket relies on that property of the expander. As Sam noted, we could introduce `letrec-syntaxes+let*-values', but that breaks existing tools. Changing the semantics of `letrec-syntaxes+values' is more backward-compatible in practice. For those rare cases where you want the old `letrec-syntaxes+values' (e.g., the expansion of `#%stratified-body'), it's easy to force the old semantics by adding an initial binding clause [() (begin (if #f id (values)))] where `id' is the last variable in the sequence of bindings. Then, all bindings are forced into a single `letrec'-like set. _________________________________________________ For list-related administrative tasks: http://lists.racket-lang.org/listinfo/dev