"Perfection is Achieved Not When There Is Nothing More to Add, But When There Is Nothing Left to Take Away"
With the specter of 1.0 approaching, here's a thread celebrating the cancers that should, with the benefit of hindsight, not have seen the light of day and that still can be removed nice and cheap (you can be sure it's cheaper now than it will be later, tutorials, stackoverflow and books notwithstanding)!
Even half-baked ones are cheaper to remove and readd than to keep and remove later - that gut feeling is right and you'll end up not readding them anyway - when writing the following post 5 years from now, do you really want it to be full of things you knew about but didn't act upon? http://www.informit.com/articles/article.aspx?p=2425867
I've started the party with https://github.com/nim-lang/Nim/pull/7669 - the dead code elimination option is indisputably useless.
Here are a few more, just to get the discussion going :)
What else would you kill off?
bitsets - why are these even in the language and not a library?
Because they're SUPER USEFUL in game development, and from what I can tell lots of people use Nim for game development.
You need resistances in your RPG?
type
Element* = enum
eFire, eWater, eEarth, eAir
var myCharacterResistances: set[Element]
myCharacterResistances.incl eFire
if enemyAttack.element notin myCharacterResistances:
echo "PREPARE YOUR ANUS"
You need to make a tile-based game?
type
OverworldTileProperty* = enum
otpWater, otpLava
if otpWater in tiles[playerPosition + playerMovement]:
echo "Dude, only Jesus can walk on water"
elif otpLava in tiles[playerPosition + playerMovement]:
echo "FEEL THE BURN!"
Some even use them for game options, intrinsics, key items, etc. etc. As a game developer, this is actually one of the things that made me love Nim. Instead of using macro voodoo to get bitarrays (like in C) or needing an external dependency (like in most other languages), Nim's system.set is everywhere, it's simple and extremely fast.
Also, Nim takes a lot of inspiration from Pascal and if I remember correctly bitsets are a native type there too.
Regarding the other points, they're all very reasonable. I personally almost never use exceptions, so if Araq wants to go the Rust/Go route is fine by me.
bitsets
I use them almost in every place, and I suppose the compiler does the same.
exceptions
I would not remove them, but it piss me off when they are used in the stardard modules. I'd rather check if the result is equals to -1 or is none than have to handle an exception when trying to stablish a new connection.
a huge standard library
I do agree there seems to be really old modules that no one use anymore. But there are good reasons for having one:
Now, system definitely does need a refactoring. You can find there strings, seqs, garbage collection, file handling, stream handling, exception handling ... I'm sure that everything related to files and GC could be separated from the main module. Not that you are going to stop the GC or open a new file in every module of your project.
Also nim could use better names for modules. 'os', 'ospaths', 'osprocs' are confusing. Maybe rename osprocs to 'process', and 'ospaths' to 'paths'.
bitsets
a really nice macro? also, backend compiler optimizers are pretty good at getting perf for these kinds of ops anyway, and with fewer features in the nim compiler, there's more room in there for good compiler features - better error messages, better transformations..
exceptions, used in the standard modules
only thing worse than exceptions is both-exceptions-and-something-else :)
exceptions, rust + unwrap
rust unwrap only gets used in old examples - there's ? for production code. Nim, thanks to its great syntactic flexibility, could do even better with a macro and a block - being explicit about ignoring errors is a good thing, just like Nim does with discard already.
std lib, lots of alternatives
std lib, nimble means dead
if they're useful, they get maintained and if they're not, nimble repo remains a place to keep them forever, unchanged and compatible with whatever other code that manages to use them successfully - combined with semantic versioning, you get the best of all worlds - stability for old stuff, promotion/accessibility for good and useful code and choice for developers
std lib, refactoring
The desired refactoring doesn't happen because it's in the std lib. If it's not in the std lib, it's cheap and easy to refactor letting the old version stay forever frozen in time.
std lib, huge
all of wrappers, most of pure.. why is json, htmlparser, smtp in there??? madness.. there's even an FTP client and two, yes TWO http servers!.. then there's core and std that are just plain weird - what goes where? posix, that's a pipe dream if there ever was one - out it goes to be replaced by https://github.com/nim-lang/Nim/pull/5698 as an external nimble lib, easy.
bring it on, all the radical stuff you'd love to change! only time will tell if the regret article will have yours and it'll be fun to look back :)
What else would you kill off?
Nim already has the ability to do OO style polymorphism without method, I think for those relatively rare cases that this is useful something other than method should be provided, maybe something like Ada 2005 interface types. I thought that's what the vtref stuff from the older concepts section of the docs was going to address, but it's gone down the memory hole. What happened?
Just enforce a particular naming style, be it camelCase or snake_case.
Is there a killer argument for these that I'm missing? I find explicit conversion more readable.
I think interfaces or something akin to them would be much more useful for the language than methods. I don't know how hard this is to implement - that's not why I'm suggesting it - I just don't find methods particularly useful.
I don't generally like exceptions - but I've also been told not use things like nil and to prefer things like exceptions. I think this needs to be sorted out and we either need to go back to doing things in a C like / some other manner or fully embrace exceptions. Or we could invent somethning here - but the current situation isn't ideal.
Converters - meh I don't find them particularly useful but I also don't find them harmful. I think they could go just to reduce a feature that probably most people don't use.
I think there's been some progress made on shrinking the stdlib and getting rid of some modules or moving some to external libs. That work should continue.
Some modules I'd personally get rid of - color, 2d/3dmath all of the db related libraries
There are others I'd consider too but I think that's a start...
Bitsets - @krux02 - what's the alternative? Could you provide an example or something? I'm also guessing they're pretty relied on throughout the Nim stdlib... What's the urge to get rid of them? What real harm does including them cause? I understand that they could be replaced with more useful features, but something equivalent or close to has to be there.
Auto formatting code - yeah some tool that the vscode extension and other editors could use would be great, I agree.
I agree with Arrrrrr's points about the system lib and general refactoring / renaming suggestions.
Compiler features I'd remove
Converters - rarely used feature that complicates the compiler
{.discardable.} - I hate this pragma with a passion
Enums with holes - barely supported in the compiler, might as well remove them since distinct types can be used instead
TaintedString - has basically zero maintenance cost, but it's just another feature that nobody ever uses
from x import nil - this is a terrible idea and is mostly used by people new to Nim, who don't fully understand why it's terrible
Compiler features I'd not remove
Tags - very rarely used, but the feature has potential and I don't think it complicates the compiler much
Exceptions - I don't like them, but they are good to have for integration with C++/JS projects
Standard library
I agree that the standard library is to big, it's a graveyard of unmaintained modules. Some modules that could be removed: complex, rationals, nre, strtabs, strmisc, marschal, events.
Exceptions are hard to replace and have their benefits, it's worth its own topic.
Focusing on the stdlib: hopefully already intended, but removing deprecated modules and procs, as well as md5 and asyncftpclient. md5 is just an attractive nuisance of a cryptographic hashing algorithm, good enough to look appealing but horridly insecure, and to the extent the stdlib has one (there are good arguments for it), it should probably be SHA2. asyncftpclient implements a decreasingly relevant protocol.
The asyncio, ftpclient, sockets, and rawsockets modules have been deprecated since version 0.11.
There are a couple dozen procs through other modules: proc `-`(a, b: Time): int64 {..}, proc fromSeconds(since1970: float): Time {..}, proc fromSeconds(since1970: int64): Time {..}, proc toSeconds(time: Time): float {..}, proc getLocalTime(time: Time): DateTime {..}, proc getGMTime(time: Time): DateTime {..}, proc getTimezone(): int {..}, the various isSpace/isAlpha/isLower/isUpper/capitalize procs, et cetera.
Agree on several other non-deprecated stdlib modules as well, e.g., strtabs and having two different regex modules.
Ill try to show that Nim 1.0 programming language standard library should not be 1:1 with the bunch of modules that currently ships with the Nim reference implementation.
Preliminaries
A programming language is not only a syntax, but also a runtime. At minimum, a runtime should offer functions for input and output. The more batteries in the runtime, the better for the end user. When designing a runtime, especially these non-functional requirements should be considered: performance, implementability, maintainability, applicability, usability and portability. The portability of runtime library can be ensured by standardizing it, whereupon it is called the language’s standard library. A standardized library ensures that source code will work across implementations and later versions. For example, standard library 1.0 source code written for compiler A implemented by company B for operating system C targeting machine D will work without refactoring with standard library 1.6 for compiler X implemented by community Y for virtual machine Z.
Definitions
Theorem
stdlib should be a non-empty proper subset of nimcc library
Proof, in 3 parts
Part 1: stdlib should be non-empty (Proof by contradiction)
If stdlib is empty, it would essentially mean that stdlib would equal system.nim. To prove that stdlib should be non-empty, it is enough to show one module that should be included in stdlib. We use macros module for this. It is stated at Nim official website, Wikipedia, and Nim in Action book that metaprogramming (hygienic term rewriting macros) is one of Nim’s core features. A standard library without macros module would therefore define a language that is not Nim.
Part 2: stdlib should be proper subset of nimcc library (Proof by reductio ad absurdum)
To prove this, it is enough to show one module that is in nimcc library but should not be in stdlib. We use winlean module for this. If nimlean is part of stdlib, it means that jsnimc must implement every function in it to be compliant. However, it is practically impossible to implement windows inside browser sandbox where javascript runtime tends to run.
Part 3: stdlib should not be a superset of nimcc library (Proof by contraction)
The label 1.0 signals that the language is production-ready. If stdlib would contain a module that is not shipped with nimcc, it would mean that no reference implementation for Nim exists, and therefore the language specification could not claim 1.0 status.
By elementary logic, the conjunction of parts 1-3 proves the theorem. QED.
Corollary
If Nim standards committee indeed decides that stdlib will not be 1:1 to nimcc library, the set of modules shipped with nimcc must be renamed to something else.
Conventionally standard library is part of the language spec. If you look at the C Reference Manual, you'll see that roughly half of the spec is devoted to specifying the stdlib. It would remove a lot of confusion if the set of .magic modules would be named as the standard library and the "standard library" something else.
Also I think that language conformance test suite should not test any modules that are not part of the language spec. Also, Rosetta Code examples should be solved (as much as possible) with the tools provided by language spec, not with help of non-standard modules like strutils or sequtils.
Controversial opinion but I'll just leave it out there because I'm a fan of Nim:
Halt Nim 1.0 until Nim 2.0 destructors suggested in https://github.com/nim-lang/Nim/wiki/Destructors is standardized. Eventually for systems programming people will want to do manual memory management. It also gives you an extra market so people don't just discard Nim just because it has a thread unsafe GC.
The market for manual resource management and RAII will never end and C++ will always be there for this. Why not penetrate this area where people advocate Rust so much? Systems/Games people want fully deterministic performance more than safety afaik.
Also, with package repo... (https://github.com/nim-lang/packages/blob/master/packages.json) does NOT look scalable to me.
Just saying. Thanks for reading.
@aedt I think it's a question of resources.
Given the current promising state it would be better to release now, garnering interest and goodwill and probably new hands to help on ironing bugs and use cases that the current tiny community doesn't need in my opinion.
Also that allows those with interest to pitch in before the door is closed. The current GC/manual memory management is already good enough to start doing productive stuff with Nim (alloc0, allocShared, ptr object).
+1, mratsim.
What I want is convenience and still catering for people who wanted more performance for low level stuff. Convenient and practical.
@aedt don't really think that is a good idea at all re halting Nim 1 for destructors.
Nim can be/is a good general purpose language.
If you look at any top 10 programming languages list only C and C++ have manual memory management. Most top 5 lists now days will also include Python, Javascript, Java and C#. The majority of programmers use GC languages.
So why limit all the majority to satisfy a minority of programmers by holding back version 1?
Most GC based languages have challenges and trade offs when it comes to threads and for most purposes Nim's thread model while it may not be ideal is good enough.
This Perfecting Nim thread is the wrong mental frame.
No programming language is perfect. They all have trade offs. Like every other language Nim will not be perfect. So its time to get over that idea, release Nim 1.0 this year, and the destructors can continue to be worked on for version 2.
If perfection or nearing perfection was a requirement for a successful language then languages like PHP and Javascript would not have enjoyed the success they have.
We are talking past each other due to multiple possible interpretations of english language terms (do we need a technical standard for english?).
I'm using the term standard in the sense of technical standard as described in Wikipedia. Let's denote a standard library interpreted this way as a standardised library.
However, the Nim community seems to interpret the term standard as an adjective as in "a standard hotel room", - synonym with terms such as normal, usual, baseline, customary or prevailing. Let's denote a standard library interpreted this way as a de-facto library.
I'm using the term Nim 1.0 language (specification) in the sense of ISO/IEC 9899:2011 language (specification), which includes, among other things, the C standard library. However, the Nim community seems to interpret the term Nim 1.0 language in stricter sense as the things specified in Nim manual (specification).
I'm inclined to agree that at this point of Nim language maturity there is no need to rigorously specify a standarised library. However, the need may raise later when competing implementations start to appear. The BASIC programming language is a cautionary example of how a language may disintegrate into non-compatible dialects with their own sets of documentation if no adherence to a specification is required (and with things like MicroPython, Python seems dangerous too...).
With these readings in mind, it makes sense to state that the de-facto library that ships as part of the Nim reference implementation is not part of the Nim language specification and therefore out-of-scope problem in perfecting Nim. Some concerns still remain:
I hope this helps.