Hi, I am new to nimlang. I got a problem when I learn redblackBST structure by nimlang.Here is part of my code:
type
Node* = ref object of RootObj
key: string
value: int
N: int
color: bool #father node chain to it color
left: Node
right: Node
proc rotateLeft*(node:Node): Node =
var x: Node = node.right
node.right = x.left
x.left = node
x.color = node.color
node.color = RED
x.N = node.N
node.N = 1 + size_node(node.left) + size_node(node.right)
return x
type
RedBlackBST* = ref object of RootObj
root:Node
proc size*(rb:RedBlackBST): int =
return size_node(rb.root)
proc put_node*(node:Node, key:string, value:int): Node =
if node == nil:
return Node(key:key, value:value, N:1, color:RED, left:nil, right:nil)
if key > node.key:
node.right = put_node(node.right, key, value)
elif key < node.key:
node.left = put_node(node.left, key, value)
else:
node.value = value
# rotate red chain
if isRed(node.right) and not isRed(node.left):
node = rotateLeft(node) # Error: 'node' cannot be assigned to
elif isRed(node.right) and isred(node.left.right):
node = rotateRight(node) # Error: 'node' cannot be assigned to
elif isRed(node.left) and isRed(node.right):
flipColors(node)
node.N = size_node(node.left) + size_node(node.right) + 1
return node
And I got error messages like this :
# Error: 'node' cannot be assigned to
According the result of google, it seems like nim can't change ref object, so I am wonder what is right method to sovle this situation.
I think it's because you try to mutate the node parameter. Parameters are immutable by default see https://nim-lang.org/docs/tut1.html#procedures-parameters.
From the doc:
If a mutable variable is needed inside the procedure, it has to be declared with var in the procedure body.
They have an example in the url above.
If you don't want to mutate you could use the result name instead. See https://nim-lang.org/docs/tut1.html#procedures-result-variable.
change the signature from proc put_node*(node:Node, key:string, value:int): Node =
to
proc put_node*(node: var Node, key:string, value:int): Node =
That's the wrong solution though as you already return the new node. Instead use this fragment:
# rotate red chain
if isRed(node.right) and not isRed(node.left):
result = rotateLeft(node) # Error: 'node' cannot be assigned to
elif isRed(node.right) and isred(node.left.right):
result = rotateRight(node) # Error: 'node' cannot be assigned to
elif isRed(node.left) and isRed(node.right):
flipColors(node)
result = node
else:
result = node
result.N = size_node(node.left) + size_node(node.right) + 1