[racket-dev] except-out oddity
About a month ago, Matthew Flatt wrote:
> At Sat, 12 Feb 2011 23:28:47 -0500, Eli Barzilay wrote:
> > Using (except-out whatever x) will omit not only `x', but also any
> > other names that `x' is provided as. For example:
> >
> > (module A racket
> > (define x 1)
> > (provide x (rename-out [x y])))
> > (module B racket
> > (require 'A)
> > (provide (except-out (all-from-out 'A) x)))
> > (module C racket
> > (require 'B)
> > y) ; error
> >
> > and it goes the other way too (excluding `y' and trying to use `x').
> > When I saw this, it seemed familiar so I looked at the docs. My guess
> > is that this:
> >
> > The symbolic export name information in the latter provide-specs is
> > ignored; only the bindings are used.
> >
> > is saying that the above is expected. If so, then it looks like it
> > should definitely be clarified, maybe move this sentence after the
> > example, explain the specific (common) case of excluding a name that
> > was provided with a different name, and also adding an example for
> > this?
>
> Ok, I'll try to clarify in the docs.
>
> > But at a higher level, is there a reason to not look at the name?
>
> I think it interacts badly with `require'- and `provide'-generating
> macros.
FWIW, here's another very confusing situation I just ran into:
(module A racket/base
(require racket/provide (for-syntax racket/base))
(require (prefix-in r: r5rs))
(provide (except-out
(filtered-out (lambda (x) (regexp-replace #rx"^r:" x ""))
(all-from-out r5rs))
map)))
it really seems weird to require `r:map' as the exclusion at that
point. Worse, if I'd do this with `racket/base' instead of `r5rs',
then this would work, but for a very obscure reason.
> > It seems bad in that the two options of
> > 1. (define x y) (provide x)
> > 2. (provide (rename-out [y x]))
> > can lead to a different result, where the second one ties the two
> > names for this kind of filtering.
>
> I'm not sure I understand what you mean. Do you mean that `x' is
> different from `(rename-out [y x])' when wrapped with `(except-out
> ... y)'?
No, I'm talking about a situation where you want to provide some `old'
name under a `new' name -- one way to do this is:
(define new old) (provide new)
and another is
(provide (rename-out [old new]))
It looks like the two are doing the same, but there's a potential
confusing problem with the second, if you get to a module that has
both names and wants to exclude only one.
> > It's also weird that the two names are the same for `except-out'
> > but in an `except-in' they're still separate.
>
> If I'm following, then I think it derives from the difference
> between bindings and uses and how those interact with macros.
>
> A variant of `except-out' that refers to external names instead of
> internal bindings may be useful, too.
That's what I think the default should be -- all of these weird cases
are a result of using the internal names where it seems that the
external ones should be used.
--
((lambda (x) (x x)) (lambda (x) (x x))) Eli Barzilay:
http://barzilay.org/ Maze is Life!