Skip to content

Fusion and stdlib evolution #310

Closed
Closed
@Araq

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

  1. 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.
  2. Introduce a std2 namespace as an alternative to an experimental 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 of type AbsoluteDir = distinct Path.
  • For strutils we like to use more of openArray[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.

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions