"Error: Undeclared identifier" when trying to return a <Node> from a procedure

Viewed 639

I post here a specific problem using a library (grim) in Nim, but the underlying concepts are still not super clear to me so I appreciate a solution coming with an explanation.

I would like to make a procedure returning a node. The example below is not really useful but makes the point: I want to return node but I apparently don't know what type it is.

import grim
import sequtils

proc get_a_node_with_label(graph: Graph, label: string): Node =
  for node in graph.nodes:
    if node.label == label:
      return node

var g = newGraph("graph")
let n1 =  g.addNode("n1", %(Name: "first"))
let n2 =  g.addNode("n2", %(Name: "second"))

var aNode = get_a_node_with_label(g, "n2")

i get an Error: undeclared identifier: 'Node', but the type of "node" in the loop is "Node", if I echo node.type.

How should I deal with types on this occasion? What output should I declare in the procedure?

Thanks Andrea

PS: I apologize if the question is not well asked, and I'm happy to improve it with your guidance.

1 Answers

You probably installed the grim library through nimble install grim. That gave you the grim-0.2.0, released early this year. The point is that Node was private in that release, so your code cannot access it.

You can opt to install the latest code, which at some point this year made Node and others public, with:

$ nimble uninstall grim
$ nimble install grim@#devel

Or you can make the object public in your computer, editing (probably) ~/.nimble/pkgs/grim-0.2.0/grim/graph.nim:

30 Node = ref object

to

30 Node* = ref object

The former includes the latest code, and includes 40ish commits. On the downside, your build will be hard to reproduce, because you cannot pin the grim version.

The later should allow you to compile locally, but you will run into problems if you intend to distribute your code (i.e. forcing you or your users to patch the grim source).

You could also open an issue at the github repo, asking the author to tag a new version.


You can get objects which class is Node (aka Node objects), but you cannot write "Node" in your code, and the only way of creating a Node object is through code that has access to the Node private class (i.e. in the same file). It is usually some kind of newNode or getNode.

So you could get a Node inside your code, and pass it around, but cannot write "Node". E.g.

import grim

var g = newGraph("graph")
let n1 = g.addNode("n1", %(Name: "first"))

# This works happily
let node = g.node(n1)  # This assigns a Node object to "node"
echo node              # This passes the Node object to a $ proc.

# This fails to compile, albeit being functionally the same code,
# because your program doesn't know what "Node" is.
let node1: Node = g.node(n1)
Related