There's a few breaking changes that come to my mind, though mostly limited to suggestions solving issues which have required me to change programming architectures or idioms to work around.
These items make writing certain kinds of software, especially system software, more difficult: * Provide `openArray` and `var openArray` arguments instead of `string`'s or `seq`'s consistently across the standard library. Change standard library modules (especially std/net) to consistently provide `var openArray` variants in addition to or instead of `var string` or `seq[T]` for mutable data blocks. It'd also be consistent with switching to ORC and move semantics and would be a good target for a Nim v2.0 (non-syntax related but breaking). The reason is that the usage of `strings` or even `seq[T]` across the std-lib forces semantics that limit the ability to implement things like zero-copy networking or non-heap code and other useful semantics without rewriting the entire networking stack (not just std/net, but also std/selectors, std/asyncnet, etc). It also is important for strings in the std-lib as well. I'd be willing to write an RFC for this if there's not one. * Provide a `SomeString` type and use it consistently in the stdlib Related to the previous item. This would enable more ecosystem provided string implementations using COW, [ropes](https://en.wikipedia.org/wiki/Rope_\(data_structure\)), or [IO lists](https://bignerdranch.com/blog/elixir-and-io-lists-part-1-building-output-efficiently/). String manipulation can be relatively slow in Nim so it'd be a nice boon. Currently to provide custom COW strings you'd need to either convert to `std/string`'s regularly or re-implement good chunks of the std-lib. Perhaps something like `SomeString` could be used instead of `string`. Though I think UTF8'ness should be _very_ separate from this change. This is purely about data semantics, not a Py3-esque redo all string semantics. Here are some more nice-to-have improvements: * Module actions / triggers on import Relying on `include` imposes some limitations for library authors. It's also not obvious when a module needs to be `included` except via docs. One important case is interacting with some C FFI's requires a blob of custom C code to be spit out. Sometimes there's just a need to run a Nim macro in the current scope. Include also doesn't offer the ability to export the trigger behavior. I don't know what solutions might have been discussed already. A few options spring to mind: * providing a Python like `__init__.py` file * splitting out `include file` vs `using module` distinction like Elixir does with [using](https://blog.appsignal.com/2021/10/26/how-to-use-macros-in-elixir.html). I prefer the Elixir style where a `__using__` macro can be provided. Perhaps it could be a pragma like `macro someBehavior() {.using.} = ` or `proc someBehavior() {.onimport.} = `. It's less confusing than Python's `__init__.py` scheme IMHO. * Default enum scoped names It's a productivity killer to remember that for arguments of type `arg2: MyEnum` you need to use `'ml'` prefix for this enums like `mlOpt1`, `mlOpt2`, etc. It also reduces discoverability as `nimsuggest` doesn't autocomplete either `MyEnum.Opt1` nor by manually triggering `foobar(arg2: <Autocomplete>`. I'm not sure if improving this actually requires breaking changes.