[racket-dev] except-out oddity

From: Matthew Flatt (mflatt at cs.utah.edu)
Date: Mon Feb 14 08:09:38 EST 2011

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

> 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 ...

> 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.

> And BTW, it's also surprising that the exceptions are provide-specs,
> which makes these:
>   (provide (except-out (all-from-out 'A) (rename-out [y foo])))
>   (provide (except-out (all-from-out 'A) (prefix-out foo y)))
> be the same as the above.  Is this ever useful?

I think I've probably used `struct-out' in the second part of
`except-out', but that's the only example that comes to mind.

Posted on the dev mailing list.