I recently tried to use the prelude module for the first time, and it was not working for me. I was using "import std/prelude" instead of "include std/prelude". In hindsight it makes sense but it was not obvious to me at all. Perhaps this is clear on the documentation but I missed it.
I wonder if it would make sense to "special case" the prelude module and make it behave as an include when you import it?
Another annoying thing about it is that using it results in warnings unless you use each and every one of the modules that prelude imports. IMHO having a standard nim "feature" such as this one that results in having several warnings that you must teach yourself to ignore is not a great idea. Could that be special cased too?
BTW, simply adding:
export os, strutils, times, parseutils, hashes, tables, sets, sequtils, parseopt, strformat
At the end of prelude.nim fixes _both of the issues I had (i.e. import now works and also I don't get the "imported and not used" warnings when the prelude imports are not used).
Could we make that change to prelude.nim? Would there be any drawback to this change?
Generally, no you should not use include over import, but for prelude or a prelude-like thing it's what I prefer. IIRC I did the same for Karax, maybe it got changed later via a PR.
If prelude did import <list>; export <list> then it should be a file you should import, not include. So maybe turn it into import std/common.
We recommend import/export throughout - but rather than using a single prelude, we build a hierarchy (preludes are kind of ugly in general because they include stuff you don't need and often miss stuff you do need)..
https://status-im.github.io/nim-style-guide/language.import.html gives some detail but basically the idea is that if you compose a type using types from other modules, you also export those modules, or you run a significant risk of having different behavior of the same type in different modules, specially when there are matching overloads (such as often happens for hash and similar functions).
The end result is that your import lists are generally short and reflect the real dependencies of the code which makes it easier to reason about.
The disadvantage of import/export is that you lose the module names.
For example you could do:
include std/prelude
echo times.fromUnix(0)
But if it changed to import common you'd have to write this instead:
import std/common
echo common.fromUnix(0)
Admittedly this wouldn't be much of a problem for the stdlib where qualifying with the module name is almost never used, but it's why I use include for my own project's "prelude".