[racket-dev] Semantics of struct-out with except-out

From: Sam Tobin-Hochstadt (samth at cs.indiana.edu)
Date: Tue Jul 15 11:00:19 EDT 2014

On Tue, Jul 15, 2014 at 10:12 AM, J. Ian Johnson <ianj at ccs.neu.edu> wrote:
> Code will break if it uses struct to produce structs, provides a renamed an accessor function, and uses an unhygienic feature to name the field.
> The features I know of are struct-copy, struct* match patterns, and contract-out's struct form.

The backwards compatibility is a concern, but even more so, I don't
think it makes sense for hiding a particular identifier from provide,
or renaming it, to change the _contents_ of the static struct info. If
there was an explicit option in `struct-out` to do that, it would make
more sense, but `except-out` should not affect anything but the
identifiers named.

> No one but me probably did this, and that's what led to my discovery of the unhygienic state of struct-copy and my previous regex-based PR to "fix" it.
> I don't /need/ to rename fields, since in the case that a field accessor is renamed to something entirely different (e.g., Foo-x => Qux), a renamed field doesn't quite benefit readability of a struct-copy that uses field "x". If renaming Foo-x to Foo-y, then a x -> y rename is helpful. I have not yet come across a need for this however.
> I can wait on this feature of struct-out (and probably contract-out's struct form as well).

If we don't actually have a need for this, then let's wait, since it
seems like it adds a bunch of complexity.


> Thanks,
> -Ian
> ----- Original Message -----
> From: "Sam Tobin-Hochstadt" <samth at cs.indiana.edu>
> To: "J. Ian Johnson" <ianj at ccs.neu.edu>
> Cc: "dev" <dev at racket-lang.org>
> Sent: Tuesday, July 15, 2014 9:35:01 AM GMT -05:00 US/Canada Eastern
> Subject: Re: [racket-dev] Semantics of struct-out with except-out
> On Tue, Jul 15, 2014 at 9:23 AM, J. Ian Johnson <ianj at ccs.neu.edu> wrote:
>> I'm working on enhancing struct-info to carry field names as symbols to do nice hygienic things:
>> http://lists.racket-lang.org/users/archive/2014-July/063271.html
>> I now see that struct-out always provides all field accessors in the static struct-info associated with the struct identifier.
>> This means the following produces (list 0 1) instead of an error saying that Foo-x is undefined, or something along those lines:
>> #lang racket/load
>> (module A racket
>>   (struct Foo (x y))
>>   (provide (except-out (struct-out Foo)
>>                        Foo-x)))
>> (module B racket
>>   (require 'A)
>>   (match (Foo 0 1)
>>     [(Foo x y) (list x y)]))
>> (require 'B)
>> To make struct-out not so greedy about what it provides would require a backwards-incompatible change. The problem then is, should we (I) do it?
> No, the current behavior is reasonable -- static struct info provides
> access to the accessors.
>> Part of me says yes for "intuitive semantics" and part of me says no because the implications are that struct-info values will have to be meticulously checked and rebound to mangled identifiers with new information when passing through provide-specs that can affect struct identifiers.
>> Should that burden be pushed to future provide-spec implementors? Should it already have been?
>> The alternative is to provide special syntax in struct-out to do all the "common" provide-spec stuff and still not play nice with other provide-specs.
>> The upside to this is no name mangling, but the downside is yet more special syntax for what provide-specs should already do, IMHO.
>> I'm planning to extend struct-out to allow renaming the fields associated with a struct so the following (contrived example) is possible:
> I think this should be delayed to a separate change. Are there cases
> in the code base currently where this would be used?
> Sam

Posted on the dev mailing list.