Documentation: directly use ref object + fields (#6598)
This commit is contained in:
parent
ac5dff2e04
commit
e7c09512d2
5 changed files with 48 additions and 37 deletions
|
|
@ -9,26 +9,26 @@ The following example shows a generic binary tree can be modelled:
|
||||||
|
|
||||||
.. code-block:: nim
|
.. code-block:: nim
|
||||||
type
|
type
|
||||||
BinaryTreeObj[T] = object # BinaryTreeObj is a generic type with
|
BinaryTree*[T] = ref object # BinaryTree is a generic type with
|
||||||
# with generic param ``T``
|
# generic param ``T``
|
||||||
le, ri: BinaryTree[T] # left and right subtrees; may be nil
|
le, ri: BinaryTree[T] # left and right subtrees; may be nil
|
||||||
data: T # the data stored in a node
|
data: T # the data stored in a node
|
||||||
BinaryTree[T] = ref BinaryTreeObj[T] # a shorthand for notational convenience
|
|
||||||
|
|
||||||
proc newNode[T](data: T): BinaryTree[T] = # constructor for a node
|
proc newNode*[T](data: T): BinaryTree[T] =
|
||||||
|
# constructor for a node
|
||||||
new(result)
|
new(result)
|
||||||
result.data = data
|
result.data = data
|
||||||
|
|
||||||
proc add[T](root: var BinaryTree[T], n: BinaryTree[T]) =
|
proc add*[T](root: var BinaryTree[T], n: BinaryTree[T]) =
|
||||||
|
# insert a node into the tree
|
||||||
if root == nil:
|
if root == nil:
|
||||||
root = n
|
root = n
|
||||||
else:
|
else:
|
||||||
var it = root
|
var it = root
|
||||||
while it != nil:
|
while it != nil:
|
||||||
var c = cmp(it.data, n.data) # compare the data items; uses
|
# compare the data items; uses the generic ``cmp`` proc
|
||||||
# the generic ``cmp`` proc that works for
|
# that works for any type that has a ``==`` and ``<`` operator
|
||||||
# any type that has a ``==`` and ``<``
|
var c = cmp(it.data, n.data)
|
||||||
# operator
|
|
||||||
if c < 0:
|
if c < 0:
|
||||||
if it.le == nil:
|
if it.le == nil:
|
||||||
it.le = n
|
it.le = n
|
||||||
|
|
@ -40,20 +40,28 @@ The following example shows a generic binary tree can be modelled:
|
||||||
return
|
return
|
||||||
it = it.ri
|
it = it.ri
|
||||||
|
|
||||||
iterator inorder[T](root: BinaryTree[T]): T =
|
proc add*[T](root: var BinaryTree[T], data: T) =
|
||||||
# inorder traversal of a binary tree
|
# convenience proc:
|
||||||
# recursive iterators are not yet implemented, so this does not work in
|
add(root, newNode(data))
|
||||||
# the current compiler!
|
|
||||||
if root.le != nil: yield inorder(root.le)
|
iterator preorder*[T](root: BinaryTree[T]): T =
|
||||||
yield root.data
|
# Preorder traversal of a binary tree.
|
||||||
if root.ri != nil: yield inorder(root.ri)
|
# Since recursive iterators are not yet implemented,
|
||||||
|
# this uses an explicit stack (which is more efficient anyway):
|
||||||
|
var stack: seq[BinaryTree[T]] = @[root]
|
||||||
|
while stack.len > 0:
|
||||||
|
var n = stack.pop()
|
||||||
|
while n != nil:
|
||||||
|
yield n.data
|
||||||
|
add(stack, n.ri) # push right subtree onto the stack
|
||||||
|
n = n.le # and follow the left pointer
|
||||||
|
|
||||||
var
|
var
|
||||||
root: BinaryTree[string] # instantiate a BinaryTree with the type string
|
root: BinaryTree[string] # instantiate a BinaryTree with ``string``
|
||||||
add(root, newNode("hallo")) # instantiates generic procs ``newNode`` and
|
add(root, newNode("hello")) # instantiates ``newNode`` and ``add``
|
||||||
add(root, newNode("world")) # ``add``
|
add(root, "world") # instantiates the second ``add`` proc
|
||||||
for str in inorder(root):
|
for str in preorder(root):
|
||||||
writeLine(stdout, str)
|
stdout.writeLine(str)
|
||||||
|
|
||||||
|
|
||||||
Is operator
|
Is operator
|
||||||
|
|
|
||||||
|
|
@ -102,6 +102,14 @@ collector to not consider objects of this type as part of a cycle:
|
||||||
left, right: Node
|
left, right: Node
|
||||||
data: string
|
data: string
|
||||||
|
|
||||||
|
Or if we directly use a ref object:
|
||||||
|
|
||||||
|
.. code-block:: nim
|
||||||
|
type
|
||||||
|
Node = ref object {.acyclic, final.}
|
||||||
|
left, right: Node
|
||||||
|
data: string
|
||||||
|
|
||||||
In the example a tree structure is declared with the ``Node`` type. Note that
|
In the example a tree structure is declared with the ``Node`` type. Note that
|
||||||
the type definition is recursive and the GC has to assume that objects of
|
the type definition is recursive and the GC has to assume that objects of
|
||||||
this type may form a cyclic graph. The ``acyclic`` pragma passes the
|
this type may form a cyclic graph. The ``acyclic`` pragma passes the
|
||||||
|
|
|
||||||
|
|
@ -5,8 +5,7 @@ Example:
|
||||||
|
|
||||||
.. code-block:: nim
|
.. code-block:: nim
|
||||||
type # example demonstrating mutually recursive types
|
type # example demonstrating mutually recursive types
|
||||||
Node = ref NodeObj # a traced pointer to a NodeObj
|
Node = ref object # an object managed by the garbage collector (ref)
|
||||||
NodeObj = object
|
|
||||||
le, ri: Node # left and right subtrees
|
le, ri: Node # left and right subtrees
|
||||||
sym: ref Sym # leaves contain a reference to a Sym
|
sym: ref Sym # leaves contain a reference to a Sym
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1511,8 +1511,7 @@ operators perform implicit dereferencing operations for reference types:
|
||||||
.. code-block:: nim
|
.. code-block:: nim
|
||||||
|
|
||||||
type
|
type
|
||||||
Node = ref NodeObj
|
Node = ref object
|
||||||
NodeObj = object
|
|
||||||
le, ri: Node
|
le, ri: Node
|
||||||
data: int
|
data: int
|
||||||
var
|
var
|
||||||
|
|
|
||||||
11
doc/tut2.rst
11
doc/tut2.rst
|
|
@ -104,8 +104,7 @@ Example:
|
||||||
|
|
||||||
.. code-block:: nim
|
.. code-block:: nim
|
||||||
type
|
type
|
||||||
Node = ref NodeObj # a traced reference to a NodeObj
|
Node = ref object # a reference to an object with the following field:
|
||||||
NodeObj = object
|
|
||||||
le, ri: Node # left and right subtrees
|
le, ri: Node # left and right subtrees
|
||||||
sym: ref Sym # leaves contain a reference to a Sym
|
sym: ref Sym # leaves contain a reference to a Sym
|
||||||
|
|
||||||
|
|
@ -155,8 +154,7 @@ An example:
|
||||||
nkAdd, # an addition
|
nkAdd, # an addition
|
||||||
nkSub, # a subtraction
|
nkSub, # a subtraction
|
||||||
nkIf # an if statement
|
nkIf # an if statement
|
||||||
Node = ref NodeObj
|
Node = ref object
|
||||||
NodeObj = object
|
|
||||||
case kind: NodeKind # the ``kind`` field is the discriminator
|
case kind: NodeKind # the ``kind`` field is the discriminator
|
||||||
of nkInt: intVal: int
|
of nkInt: intVal: int
|
||||||
of nkFloat: floatVal: float
|
of nkFloat: floatVal: float
|
||||||
|
|
@ -482,11 +480,10 @@ containers:
|
||||||
|
|
||||||
.. code-block:: nim
|
.. code-block:: nim
|
||||||
type
|
type
|
||||||
BinaryTreeObj[T] = object # BinaryTree is a generic type with
|
BinaryTree*[T] = ref object # BinaryTree is a generic type with
|
||||||
# with generic param ``T``
|
# generic param ``T``
|
||||||
le, ri: BinaryTree[T] # left and right subtrees; may be nil
|
le, ri: BinaryTree[T] # left and right subtrees; may be nil
|
||||||
data: T # the data stored in a node
|
data: T # the data stored in a node
|
||||||
BinaryTree*[T] = ref BinaryTreeObj[T] # type that is exported
|
|
||||||
|
|
||||||
proc newNode*[T](data: T): BinaryTree[T] =
|
proc newNode*[T](data: T): BinaryTree[T] =
|
||||||
# constructor for a node
|
# constructor for a node
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue