wishi
wishi

Reputation: 7387

How to handle a seq as a return value in Nim

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.

Upvotes: 3

Views: 1716

Answers (1)

gwerners
gwerners

Reputation: 66

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'.

Upvotes: 2

Related Questions