Hi to all, in the std/tables documentation is stated: If you are using simple standard types like int or string for the keys of the table you won't have any problems, but as soon as you try to use a more complex object as a key you will be greeted by a strange compiler error (...)
Since I needed to implement a simple group by count of certain fields (4th and 2nd) of a csv dataset, I was thinking to rely on CountTable using sequence as key, like this:
import std/[tables, parsecsv, streams, os]
# classical stuff to open file and parse csv (...) omitted
csvfile.readHeaderRow() #first line is header, loaded into lookuptable
var groupCount: CountTable[seq[string]]
while csvfile.readRow():
groupCount.inc(@[csvfile.row[3],csvfile.row[1]])
and it worked... right out of the box. So my questions are: Is it OK to use sequences as keys of Tables... and in general any other object as long as Nim compiler does not complain, or there is some risk of runtime misbehaviour I should consider?
In the std/tables documentation, the example with the complex object is working also without hash proc (is never called), so... the hash for the complex object seems to be already implemented within std/tables module.
https://play.nim-lang.org/#ix=4Fei
What am I missing? May be the idea of the example was to show the inner working of std/tables for more complex objects?
One last question. In Python dictionary keys must be non-mutable data, e.g. lists cannot be used, while tuples are allowed. I guess that this restriction is because Python use reference semantics for assignments... we do not have the same limitation in Nim, i.e. it's OK to use as key a value derived by a mutable var (because it is copied), am I right?
Thank you
std / tables pulls in std / hashes: the reason seq[string] works out of the box is because that there is a hash function for a generic `seq[T]`, which in return calls the hash() function over each of its elements, of which there is already one defined for string.
nim (as of around 2 years ago) actually tries to define a pretty wide-ranging hash functions over even general arbitrary object types. if you feel that the set-it-and-forget behavior is wrong for a given type, define a new tighter overload on hash() for that specific type. (really this means that the statement in the docs for std / tables may be outdated)
it's OK to use as key a value derived by a mutable var (because it is copied), am I right?
Yes. (It Python, all variables are mutable; the limitation is about mutable values, which correspond to reference types in Nim.)