Hello nim lovers! Another portion of dumb questions from nim newbie :)
1) Consider this project structure:
app.nimble
app/
- version.txt # contains "0.1.1-3"
- utils.nim
utils.nim contains getVersion helper which just reads from file:
proc getVersion*(versionFile:string): seq[string] =
staticRead(versionFile).split('-') # static is required because I need this value at compile time
app.nimble:
const
versionFile = "app/version.txt"
# ...
task version, "Get version":
echo "Proc call: " & $(getVersion(versionFile))
echo "Inline call: " & $(staticRead(versionFile).split('-'))
Now here is the magic:
> nimble version
Executing task version in .../app.nimble
Proc call: @[0.1] <-- WTF?!
Inline call: @[0.1.1, 3]
Okay, it looks like calling staticRead is cached somehow when using a proc (cause I had "0.1" some time ago). But why, and how to avoid it?
3) Also, just curious why we have to use staticRead at all? Looks like const already marks expressions as compile-time:
const
constEval = contains("abc", 'b') # computed at compile time, no need to use staticContains or smth
data = readFile("somefile") # <-- OOPS! doesn't work at compile time
data = staticRead("somefile") # <-- will work
Cannot nim distinguish between compile/runtime and call appropriate read function accordingly?No idea about 1. Maybe --force flag will affect this?
For 2, your path is app/version.txt which suggests that it reads relative to your module. That makes sense to me. It's how import works.
For 3, Nim can distinguish. Nim cannot perform FFI at compile-time though, and readFile requires it. We could implement readFile for the Nim compile-time VM, and I would prefer to do this to be honest. Having a different API for compile-time vs. run-time is an additional burden on the programmer.
- Maybe --force flag will affect this?
How can this be?, if Nim compiler detect that your .nim(on disk) not modified, and there is already .c/.o for the .nim in /nimcache, Nim compiler will skip codegen for the .c/.o file(if the dependencies/imports also not changed). Using staticRead(x) indeed change .nim file(in memory) if you change/update the 'x', but the compiler will not know about this(the compiler hash the file on disk, not the AST in memory).
That's why, it looks cached somehow. Perhaps you can request a new feature for Nim compiler to hash the 'x' too as a dependency.
No.3 Compile time FFI
if I am not mistaken, araq has a branch of Nim implementing compile time FFI, but then abandoned/postponed because it would be a nightmare for maintainer to deal with upcoming issues related to compile time FFI while the Nim compiler itself already had many issues. But I believe, in the future we can revive this idea. It will be cool although a bit nasty.
3 is a very bad idea, we did this for os.getConfigDir() which people then used in a const section producing a binary that only works for the user who compiled the program.
People? Who?
But in any case, with great power comes great responsibility. People that use Nim should know what const does. We shouldn't baby them into thinking it's just like a 'let'.