This site is a static rendering of the Trac instance that was used by R7RS-WG1 for its work on R7RS-small (PDF), which was ratified in 2013. For more information, see Home.

Source for ticket #520

cc


    

changetime

2013-07-07 03:20:44

component

WG1 - Core

description

Mikael More writes:

  There is no description in the spec of what a library exports if it has no export library declaration, and this could very well be interpreted as something else than that in this case, all of the library's identifiers should be exported.

  Rationale:  For (library) exports, an export-all by default approach is of value in many incremental development situations.

  To give an example, a Tetris game, with rendering, keyboard input, and other libraries.  The basic idea is that, as the programmer adds modules to the code project and imports them incrementally into the Scheme environment, it is implicit that every new identifier the programmer defines in a module should be exported to all of its dependencies; The library abstraction is used as a means for subdivision/modularization/separation of code only and the code project is so small that there cannot possibly be any unexpectable identifier/export collision to talk about.

  A requirement to explicitly export symbols though, would require the programmer to add this as an extra consideration which is strictly speaking unnecessary, and would provide a clear incentive for the programmer to replace the spec-provided library functionality with a custom one; this would be an involvement of unnecessary complexity, and would also decrease the generality of the spec-provided library functionality so much that a less general name for its |import| form, such as |import-library|, would be really relevant to consider.

  I would suggest that the R7RS Library syntax should be intended to deliver for incremental development also, as this appears like the most holistic approach - the Library syntax describe a mechanism for subdivision/modularization of code as it is already, so it would make sense for it to be intended also for this use. Therefore:

  Suggestion:  I'd suggest that a clarification is added to the spec that all identifiers are exported by default, so that that is the effect absence of an export library declaration has.  A library that wants not to export any identifiers specify an export library declaration that lists no libraries, i.e. `(export)` .

The intention is that if nothing is mentioned in an export library declaration, nothing is exported.  Such libraries can be imported solely for their side effects.

Ticket #402 proposed `(export-all)`, though not the interpretation of no export declarations.  In [wiki:WG1Ballot6Results], the WG narrowly decided not to have `(export-all)` in the small language, on the grounds that it was an additional unnecessary complication, and that it was good discipline to export only what is explicitly mentioned.  One member did bring up the idea of exporting all when no declarations are present, and rejected it as violating the Law of Least Astonishment.

In addition, the question was raised whether `(export-all)` should export what is imported as well as what is defined.  There is a use case for both interpretations, analogous to public vs. private inheritance in C++.  It's not clear which version this proposal intends, though I'd guess that it's meant to export only what is defined.

id

520

keywords


    

milestone


    

owner

alexshinn

priority

major

reporter

cowan

resolution

wontfix

severity


    

status

closed

summary

A library with no export declarations should export everything

time

2013-05-13 15:59:37

type

defect

Changes

Change at time 2013-07-07 03:20:44

author

cowan

field

comment

newvalue

The WG decided by unanimous consent to take no action on this ticket.

oldvalue

2

raw-time

1373142044410382

ticket

520

time

2013-07-07 03:20:44

Change at time 2013-07-07 03:20:44

author

cowan

field

resolution

newvalue

wontfix

oldvalue


    

raw-time

1373142044410382

ticket

520

time

2013-07-07 03:20:44

Change at time 2013-07-07 03:20:44

author

cowan

field

status

newvalue

closed

oldvalue

new

raw-time

1373142044410382

ticket

520

time

2013-07-07 03:20:44

Change at time 2013-05-13 16:12:31

author

cowan

field

_comment0

newvalue

1369075080517197

oldvalue

I agree that magically exporting all violates the Law of Least Astonishment, and so I rejecdt this option.  I have, however, proposed `export-all` and `reexport` library declarations as a mandatory WG2 extension: see LibraryDeclarationsCowan for details.

In my (still very limited) experience at writing R7RS libraries, however, I find that I almost never do want to export ''everything'', other than in the situation of extending a library (which is what `reexport` is for).  For one thing, there is generally at least one new record type in each of my libraries, and I usually want to wrap the raw setters and the raw constructor in procedures that check their arguments for type and/or other things; similarly, I often want procedures that don't verify their invariants because I know they will only be called from other procedures that do verify them.  In both cases, hiding the raw versions is crucial to safety.

Given that in some libraries exporting may be more frequent than hiding, an alternative to `export-all` would be an `export-all-except` declaration.  Such a declaration would be brittle: one would have to be careful, when adding new private procedures, to add them to the `export-all-except` list as well, and the compiler would provide no support for doing so.  By contrast, if you forget to export something, you find out as soon as you run a proper set of tests that imports the library.

raw-time

1368436351106746

ticket

520

time

2013-05-13 16:12:31

Change at time 2013-05-13 16:12:31

author

cowan

field

comment

newvalue

I agree that magically exporting all violates the Law of Least Astonishment, and so I reject this option.  I have, however, proposed `export-all` and `reexport` library declarations as a mandatory WG2 extension: see LibraryDeclarationsCowan for details.

In my (still very limited) experience at writing R7RS libraries, however, I find that I almost never do want to export ''everything'', other than in the situation of extending a library (which is what `reexport` is intended for).  For one thing, there is generally at least one new record type in each of my libraries, and I usually want to wrap the raw setters and the raw constructor in procedures that check their arguments for type and/or other things; similarly, I often want procedures that don't verify their invariants because I know they will only be called from other procedures that do verify them.  In both cases, hiding the raw versions is crucial to safety.

Given that in some libraries exporting may be more frequent than hiding, an alternative to `export-all` would be an `export-all-except` declaration.  Such a declaration would be brittle: one would have to be careful, when adding new private procedures, to add them to the `export-all-except` list as well, and the compiler would provide no support for doing so.  By contrast, if you forget to export something, you find out as soon as you run a proper set of tests that imports the library.

oldvalue

1

raw-time

1368436351106746

ticket

520

time

2013-05-13 16:12:31