rhombus-prototype icon indicating copy to clipboard operation
rhombus-prototype copied to clipboard

Discourage or outright disable "namespace dumping" in requires

Open Runi-c opened this issue 4 years ago • 1 comments

Racket modules are wonderful for containerizing code, and we've been given forms like only-in and prefix-in to make imported symbol sources explicit. However, the standard behavior (i.e. the one most easily accessible, most frequently used in docs, and mostly used by racketeers) is the simple (require <module>) form, which dumps the module's entire namespace into yours, thereby obfuscating where those symbols came from when they're used.

I think that in Rhombus, the require form should default to, if not require, explicit imports - either listing imported symbols explicitly or putting them behind a prefix. This is the direction that many other languages have gone in, for example C++ defaults to making you use scope resolution operators such as std::cout to make explicit where a symbol is imported from. C++ also allows you to dump a namespace into yours using i.e. using namespace std; but this is widely considered bad practice. Similarly, other modern languages (i.e. javascript) don't even offer a means of namespace dumping, instead forcing programmers to explicitly declare their imported symbols or to bind them behind a name.

Reasoning:

  • Reading code on GitHub would be far more feasible. Currently, it's almost infeasible to read unfamiliar code without an editor capable of expansion, because modules often require many other modules and it's very often unclear where a given name might have come from. I frequently find myself doing doc searches and repo searches just to try and find where a symbol came from in order to trace a program's behavior, or just giving up entirely and downloading the repo to load into an editor.
  • Forcing explicit imports makes static analysis of individual files far easier. GitHub is able to very easily provide jump links for Javascript files without needing to actually run them through a proper parser due to their static imports.
  • Improves long-term module maintainability by reducing likelihood of name collisions caused by updates. Currently, trying to update dependencies of a module might suddenly cause your program to fail if a module adds names that were already imported by another module. This would be impossible with explicit imports.

Notes:

  • #lang lines should probably always namespace dump. It is the language you're writing in after all, its constructs should be the default.
  • Due to potentially-unhygienic macros, perfect single-file analysis is probably not possible. This is fine as long as it can be useful in the general case, plus it would encourage programmers to design programs in a way that both other contributors and github can usefully parse.

Runi-c avatar May 10 '21 19:05 Runi-c

One difficulty with namespace dumping for #lang lines, with the current way racket is organized: Starting with #lang racket would make it rather difficult to specialize to #lang racket/base, as suddenly a lot of identifiers would need to be prefixed. Unless there's an automatic way to update the code (might not work with commented-out code, but maybe that's okay), or maybe #lang racket just uses default prefixes, like the export from racket/string would by default be prefixed with string- for example.

Metaxal avatar Aug 03 '21 07:08 Metaxal