Description
Background story
We tried to move PMunch's excellent socket stream implementation from a PR against Nim's stdlib to Fusion. This PR needs the new cast(tags: [].)
construct and since fusion currently aims to support Nim version 1.2, we cannot make it available there easily. This means even though Fusion is supposed to be a staging area for the stdlib, contributing to Nim's stdlib is easier than contributing to Fusion. Clearly against Fusion's design. At the same time, Fusion is growing JS specific libraries and other helpers which don't follow our idea what Fusion should be about. Nothing against more JS specific wrappers, but Fusion aims to support its code for the next decade and JS wrappers are a poor fit for it.
At the same time, we don't need yet-another Fusion-like repository just because Fusion is used differently than we anticipated. And there are more problems with Fusion itself too: It ships both with the latest stable Nim and is installable as a Nimble package -- whenever we offer a choice we have to ensure that every choice does work and keeps working. Hence offering this choice is a bad idea.
Fusion specific proposal
Make Fusion broader in its scope. Do not ship Fusion with Nim. Fusion should target the latest stable Nim and also work with Nim devel, but not every module in Fusion needs to support eg. Nim version 1.2.
If fusion is no longer shipped with stdlib, many modules should make it into the stdlib, either in std2 or in std. Obvious candidates are: smart pointers, tree based collections, the pattern matching macro.
Proposal: Introduce a std2
namespace for Nim stdlib modules
- Allow the stdlib to grow without the Fusion staging area, for the non-controversial, simple, basic modules where it makes sense. We are already doing this, mostly.
- Introduce a
std2
namespace as an alternative to anexperimental
namespace. The problem with the "experimental" name
space is that it's not clearly defined when things are not "experimental" anymore. Also, designing an API for eg. rational numbers is much easier than designing new macros for async, yet every new module should start out as "experiemental", somehow.
And it gets worse: If we later move experimental / module
to std / module
when the module is not experimental anymore, we break code. So for backwards compatibility reasons experiemental / module
has to remain! Let's assume we introduce std / module
and then make experimental / module
refer to std / module
, like so:
# experimental module.
import std / module as m
export m
{.deprecated: "Import std / module instead".}
But now we created a situation where it's better to import experimental / module! Because that's the import that actually works with older versions of Nim! So client code becomes:
when NimVersion > (1, 5, 0):
import std / module
else:
import experimental / module
But only for the code that was updated, other old code simply uses import experimental / module
without the when
statement, which is ugly anyway. For these reasons it is much better if new, experimental modules start in the std
namespace. Or in a new std2
namespace. Whether it's experimental or not can be mentioned in the documentation, but it is expected that everything in std2
becomes non-experimental with the release of Nim 2.0.
Alternative proposal: Introduce versioning for specific modules
There is some desire to evolve core libraries further:
- For
os
, we like to have more type safety in the form oftype AbsoluteDir = distinct Path
. - For
strutils
we like to use more ofopenArray[char]
building blocks, plus we like to split it up into multiple, smaller modules. - For
io
some basic streaming abstraction that works with async might be a good idea.
However, these outlined changes cannot be applied to the existing os, strutils, io modules without severe interruptions for the people using these libraries (which is effectively everybody who uses Nim). So we can either have std2 / os
or std / os2
or maybe even std2 / os2
.
Considered, rejected alternative
An alternative that I considered was to come up with slightly different names like input_output
instead of io2
etc. That's worse because the connection between modules named io
and input_output
is unclear. There is also no clear way how to name the 3rd version of io then whereas a name like io3
is obvious.