I have two nim files:
#File A.nim
import tables, json
var myJsonData* = initTable[string, JsonNode]()
let
# a json string to be converted into a key value table
Index = %*
[
{
"name": "testname",
"key": "testKey"
}
]
for i in 0..(Index.len - 1):
myJsonData.add(Index[i]["key"].str, Index[i])
when isMainModule:
echo (myJsonData["testKey"])
and the second one imprts the first one:
#File B.nim
import A
echo (A.myJsonData["testKey"])
If I run the A.nim I get the output correctly:
{"name": "testname", "key": "testKey"}
but if I run file B.nim I get:
B.nim(4, 19) Error: type mismatch: got (Table[system.string, json.JsonNode], string)
but expected one of:
system.[](a: array[Idx, T], x: Slice[system.int])
system.[](s: string, x: Slice[system.int])
system.[](a: array[Idx, T], x: Slice[[].Idx])
system.[](s: seq[T], x: Slice[system.int])
The key of the table is a string which is a "simple standard type" as per what the documentation is saying.
Any idea what I am missing?
Thank you.
I encountered this problem too, and made an issue for it here: https://github.com/Araq/Nim/issues/2832
I assumed it was to do with generics, but perhaps it's just to do with how tables get exported.
EDIT: Araq you mention exporting .[] which would solve this problem. Now you've mentioned this, and reading http://nim-lang.org/docs/manual.html#modules-export-statement it seems all that's required is "export tables.`[]`", but unfortunately that didn't solve the issue. I am obviously not using it right or you're referring to a different export mechanism.
What is the correct usage here? It's surely going to be a common pattern whenever someone wants to use a hash table as a field that's exposed to the user.
EDIT2: On further investigation, interestingly whilst [] doesn't work in module A when used from module B, tables.add does work when used in module A (and called from module B). I can't see any obvious reason why add would work but [] wouldn't without importing tables at the call site.
Well A exports myJsonData but not tables.[].
Well I create a getTable* ():Table[string, JsonNode] proc that returned the table and the error did not change by mach.
Well then A exports getTable but not tables.[]. Add this line to your module A:
export tables.`[]`
Araq, this doesn't work unfortunately as I explained above.
Module A:
import tables
export tables.`[]`
proc useTable*[T](a: string, data: T) =
var tbl = initTable[string, T]()
tbl[a] = data
Module B:
import modulea
useTable[int]("test", 4)
When you run Module B you get:
moduleb.nim(2, 13) Info: template/generic instantiation from here
modulea.nim(6, 6) Error: type mismatch: got (Table[system.string, system.int], string, int)
Error: type mismatch: got (Table[system.string, system.int], string, int)
but expected one of:
system.[]=(a: var array[Idx, T], x: Slice[system.int], b: openarray[T])
system.[]=(a: var array[Idx, T], x: Slice[[]=.Idx], b: openarray[T])
system.[]=(s: var seq[T], x: Slice[system.int], b: openarray[T])
system.[]=(s: var string, x: Slice[system.int], b: string)
@Araq That works for me thanks.
Is there a reason why the compiler is not figuring this out on its own? If I export a variable of type T, the user of that variable might want to use features of the type T as well.
If I export a variable of type T, the user of that variable might want to use features of the type T as well.
Well but Nim's module system is scope based, not type based. Also "features of type T" is not a well defined concept: If I export a string should everything from strutils be implicitly available?
Araq, this doesn't work unfortunately as I explained above.
Yes I know, but your problem has to do with symbol lookup rules in generics/templates. It's a high priority bug for a reason.
Well but Nim's module system is scope based, not type based. Also "features of type T" is not a well defined concept: If I export a string should everything from strutils be implicitly available?
Ok, maybe the string is not the best example, as strutils is an extension of the type, is not part of the type (at least in my mind). But anyway it works now, so thank you.
xyz32: strutils is an extension of the type, is not part of the type (at least in my mind).
In your mind is a concept of classes. But Nim is based on multiple dispatch, not classes ... functions aren't "part of" any type.
A is exporting a table; its users need to know that it's a table. If you don't want that, then A should define a distinct type, and functions (such as []) that operate on that type (the borrow pragma can help), and should export one of those.