Skip to content

Instantly share code, notes, and snippets.

@dom96

dom96/a.nim Secret

Created December 7, 2015 17:42
Show Gist options
  • Save dom96/1984a7a196dddd658c2f to your computer and use it in GitHub Desktop.
Save dom96/1984a7a196dddd658c2f to your computer and use it in GitHub Desktop.
import strutils
type
NodeKind = enum
NodeKind1, NodeKind2, NodeKind3
# Only some Nodes should have children. You can't name two attributes within a
# type definition using a case statement the same as of yet (probably a bug).
# You will get a redefinition error for the attribute, even though both
# branches are never active at the same time.
Node = ref object
value: string
case kind: NodeKind
of NodeKind1:
internalChildren: ref seq[Node]
of NodeKind2:
internalChildren2: ref seq[Node]
of NodeKind3:
something: string
# So we write a custom accessor to transparently grab the correct children
# attribute for the Node
proc children(node: Node): ref seq[Node] =
case node.kind:
of NodeKind1:
return node.internalChildren
of NodeKind2:
return node.internalChildren2
else:
raise newException(ValueError, "$1 can't have children".format(node.kind))
proc newNode(kind: NodeKind, value: string): Node =
new result
result.kind = kind
result.value = value
case kind
of NodeKind1:
new(result.internalChildren)
result.internalChildren[] = @[]
of NodeKind2:
new(result.internalChildren2)
result.internalChildren2[] = @[]
of NodeKind3:
result.something = ""
proc main() =
var node = newNode(NodeKind1, "Hello World")
let childNode = newNode(NodeKind1, "Child 1")
node.internalChildren[].add childNode
# Works exactly as expected! But we have to use internalChildren and
# internalChildren2 depending on type. Now let's attempt to use our accessor
# proc to hide that complexity from us
echo node.repr
# This calls the children proc and returns the children field of the given
# nide.
var referenceToChildren = node.children
let childNode2 = newNode(NodeKind1, "Child 2")
referenceToChildren[].add childNode2
# Child 2 doesn't appear in the object structure, apparently node.children
# returned a copy of the seq[Node]-children data structure and modified it
# instead of the original object
echo node.repr
# Output:
discard """
ref 00328028 --> [value = 00329028"Hello World",
NodeKind1internalChildren = 00329048[ref 00328040 --> [value = 00328058"Child 1",
NodeKind1internalChildren = 0032a038[]]]]
ref 00328028 --> [value = 00329028"Hello World",
NodeKind1internalChildren = 00329048[ref 00328040 --> [value = 00328058"Child 1",
NodeKind1internalChildren = 0032a038[]]]]
"""
when isMainModule:
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment