3

I am running into a problem with Nim sequences and returning them from a function.

json_p.nim(42, 33) template/generic instantiation from here
json_p.nim(28, 22) Error: no generic parameters allowed for seq

Line 28 is where I define my key_list

proc get_json_keys(json_data: JsonNode) : seq =
    var key_list: seq[string] = @[] # 28
    var key: string
    for record in json_data:
        for key, value in record:
            if (not key_list.contains(key)):
                key_list.add(key)
    return key_list

I just call it from a main.

proc main() : void =     
    var file = get_url()
    var json_data = file.parseFile()

    [...]

    var key_list = get_json_keys(json_data)
    for key in key_list:
        echo key

The code works fine inside the main function.

wishi
  • 7,188
  • 17
  • 64
  • 103
  • 3
    The cause of this is that the return type of `get_json_keys` is `seq` rather than `seq[string]`. The problem is that `seq` is a type class, not a concrete type. If you replace the return type with `seq[string]`, the issue should go away. – Reimer Behrends Jul 22 '17 at 13:39
  • That is correct... I am new to Nim. Completely misread the error – wishi Jul 22 '17 at 14:10
  • 1
    Not your fault, the error message is very misleading. I noticed it because of the "template/generic instantiation" part, which can only happen if you call a template, a procedure with explicit generic parameters, or a procedure that uses a type class. – Reimer Behrends Jul 22 '17 at 14:11
  • 1
    Reimer, I think you should rewrite your comment as an answer, so it can be accepted. – sschober Aug 02 '17 at 03:59

1 Answers1

2

Problems:

*seq is a generic dynamic array an you can only add the key and all search will be linear since it's like the C language array.

*All functions returning value have a default "result" named variable. You should use it to return your values.

*Using ".contains" will make nim search the entire array in order to check. The best option is use a container with fast search.

I'll assume you need:

*a function to handle json duplicate keys and return the unique list with fast key search.

Implementation:

import json,tables

proc get_json_keys(json : JsonNode):OrderedTable[string,string]=
  #initialize the result object
  result = initOrderedTable[string,string]()
  #more info,see https://nim-lang.org/docs/json.html
  for key,value in json.pairs():
    #debugging...
    #echo key & "-" & value.getStr()
    if not result.contains(key):
      result[key]=value.getStr()

var json_data = parseJson("""{"key1" :"value1","key2" :"value2" }""")
var key_list = get_json_keys(json_data)
for key in key_list.pairs() :
  echo key

Output:

(Field0: "key1", Field1: "value1")

(Field0: "key2", Field1: "value2")


If search speed is not a issue, you can also do this way:

Implementation using seq:

proc get_json_keys(json : JsonNode):seq[string]=
  result = newSeq[string](0)
  for key,value in json.pairs():
    if not result.contains(key):
      result.add(key)

var json_data = parseJson("""{"key1" :"value1","key2" :"value2","key1":"value3" }""")
var key_list = get_json_keys(json_data)
echo key_list

Output:

@["key1", "key2"]

obs: edited my answer because seq is not immutable if declared with 'var'. It's only immutable if declared with 'let'.

gwerners
  • 66
  • 1
  • 6