I've been fighting a confusing compile time error while refactoring a larger project based on arraymancer to use generics, I've then reduced it to a small example.
The very same code compiles when included (or copy-pasted in caller scope), but doesn't when imported.
barmod.nim
import arraymancer
proc bar*[V]() =
discard newTensor[float32](0).asType(V)
main.nim
when true:
import barmod
# compile error
# Error: undeclared identifier: 'newTensor'
else:
# compiles successfully
include barmod
bar[int]()
I know this is related to declarations available at macro callsite, and I've checked that newTensor is not available there, but why is it working when calling proc is included and not imported?
Would you please explain me what is happening here?
asType proc is here
Error: undeclared identifier: 'newTensor' happens here
Thanks
Try
mixin newTensor
in the template.mixin desn't work, I get same compile time error, but it compiles successfully using bind instead.
import arraymancer
proc bar*[V]() =
bind newTensor
discard newTensor[float32](0).asType(V)
I think the answer lies in understanding this.
https://nim-lang.org/docs/manual.html#generics-delegating-bind-statements
But an explanation would be appreciated. Thanks
I've found another example of the same include vs import issue in my project
could you please explain me the difference from include and import in this context? I'm still far from understanding this
# malebolgia_generic_mod.nim
#[
import std/[enumerate]
import malebolgia
func threadFunc[T](a: openArray[T]): T =
result = a[0] + a[1]
proc run*[T](inputs: openArray[T]): seq[T] =
result = newSeq[T](inputs.len)
var m = createMaster()
m.awaitAll:
for i, item in enumerate(inputs):
m.spawn threadFunc([item, item]) -> result[i]
]#
when false:
# nim-2.0.2/lib/std/tasks.nim(97, 39) Error: undeclared identifier: 'isolate'
import malebolgia_generic_mod
else:
# compiles successfully
include malebolgia_generic_mod
when isMainModule:
echo run([1, 2, 3, 4, 5])
echo run([1.0, 2.0, 3.0, 4.0, 5.0])
I think it's a bug, that an imported module cannot find a symbol from a module that the imported module imports.
In the second example, it also has something to do with this line, where the identifier is not directly bound as a symbol but placed into the calling module to be bound later. The module task also exports std/isolation, so it shouldn't have been a problem. However, the bug was triggered when the module was indirectly imported.
I think this problem is about which of the generic proc/template/macro resolves first and in which context. I don't know if there's such rule defined.
However, the workaround seems to be explicitly importing and exporting the module and the symbols that couldn't be found.
import std/[enumerate, tasks]
import malebolgia
...
export tasks