From b52febf77e14c9aea3ece6643b585817526368f0 Mon Sep 17 00:00:00 2001 From: konsumlamm <44230978+konsumlamm@users.noreply.github.com> Date: Wed, 10 Mar 2021 08:25:50 +0100 Subject: [PATCH] Improve the lists module (#17312) --- lib/pure/collections/lists.nim | 351 +++++++++++++++++---------------- 1 file changed, 185 insertions(+), 166 deletions(-) diff --git a/lib/pure/collections/lists.nim b/lib/pure/collections/lists.nim index edb852999..82045ef76 100644 --- a/lib/pure/collections/lists.nim +++ b/lib/pure/collections/lists.nim @@ -16,11 +16,11 @@ ## # Basic Usage ## Because it makes no sense to do otherwise, the `next` and `prev` pointers ## are not hidden from you and can be manipulated directly for efficiency. - +## ## ## Lists runnableExamples: - var - l = initDoublyLinkedList[int]() + var l = initDoublyLinkedList[int]() + let a = newDoublyLinkedNode[int](3) b = newDoublyLinkedNode[int](7) c = newDoublyLinkedNode[int](9) @@ -38,8 +38,8 @@ runnableExamples: ## ## Rings runnableExamples: - var - l = initSinglyLinkedRing[int]() + var l = initSinglyLinkedRing[int]() + let a = newSinglyLinkedNode[int](3) b = newSinglyLinkedNode[int](7) c = newSinglyLinkedNode[int](9) @@ -64,52 +64,40 @@ when not defined(nimHasCursor): {.pragma: cursor.} type - DoublyLinkedNodeObj*[T] = object ## \ - ## A node a doubly linked list consists of. + DoublyLinkedNodeObj*[T] = object + ## A node of a doubly linked list. ## ## It consists of a `value` field, and pointers to `next` and `prev`. - next*: (ref DoublyLinkedNodeObj[T]) - prev* {.cursor.}: ref DoublyLinkedNodeObj[T] + next*: (DoublyLinkedNode[T]) + prev* {.cursor.}: DoublyLinkedNode[T] value*: T DoublyLinkedNode*[T] = ref DoublyLinkedNodeObj[T] - SinglyLinkedNodeObj*[T] = object ## \ - ## A node a singly linked list consists of. + SinglyLinkedNodeObj*[T] = object + ## A node of a singly linked list. ## ## It consists of a `value` field, and a pointer to `next`. - next*: (ref SinglyLinkedNodeObj[T]) + next*: (SinglyLinkedNode[T]) value*: T SinglyLinkedNode*[T] = ref SinglyLinkedNodeObj[T] - SinglyLinkedList*[T] = object ## \ + SinglyLinkedList*[T] = object ## A singly linked list. - ## - ## Use `initSinglyLinkedList proc <#initSinglyLinkedList>`_ to create - ## a new empty list. head*: (SinglyLinkedNode[T]) tail* {.cursor.}: SinglyLinkedNode[T] - DoublyLinkedList*[T] = object ## \ + DoublyLinkedList*[T] = object ## A doubly linked list. - ## - ## Use `initDoublyLinkedList proc <#initDoublyLinkedList>`_ to create - ## a new empty list. head*: (DoublyLinkedNode[T]) tail* {.cursor.}: DoublyLinkedNode[T] - SinglyLinkedRing*[T] = object ## \ + SinglyLinkedRing*[T] = object ## A singly linked ring. - ## - ## Use `initSinglyLinkedRing proc <#initSinglyLinkedRing>`_ to create - ## a new empty ring. head*: (SinglyLinkedNode[T]) tail* {.cursor.}: SinglyLinkedNode[T] - DoublyLinkedRing*[T] = object ## \ + DoublyLinkedRing*[T] = object ## A doubly linked ring. - ## - ## Use `initDoublyLinkedRing proc <#initDoublyLinkedRing>`_ to create - ## a new empty ring. head*: DoublyLinkedNode[T] SomeLinkedList*[T] = SinglyLinkedList[T] | DoublyLinkedList[T] @@ -122,32 +110,48 @@ type proc initSinglyLinkedList*[T](): SinglyLinkedList[T] = ## Creates a new singly linked list that is empty. + ## + ## Singly linked lists are initialized by default, so it is not necessary to + ## call this function explicitly. runnableExamples: - var a = initSinglyLinkedList[int]() + let a = initSinglyLinkedList[int]() + discard proc initDoublyLinkedList*[T](): DoublyLinkedList[T] = ## Creates a new doubly linked list that is empty. + ## + ## Doubly linked lists are initialized by default, so it is not necessary to + ## call this function explicitly. runnableExamples: - var a = initDoublyLinkedList[int]() + let a = initDoublyLinkedList[int]() + discard proc initSinglyLinkedRing*[T](): SinglyLinkedRing[T] = ## Creates a new singly linked ring that is empty. + ## + ## Singly linked rings are initialized by default, so it is not necessary to + ## call this function explicitly. runnableExamples: - var a = initSinglyLinkedRing[int]() + let a = initSinglyLinkedRing[int]() + discard proc initDoublyLinkedRing*[T](): DoublyLinkedRing[T] = ## Creates a new doubly linked ring that is empty. + ## + ## Doubly linked rings are initialized by default, so it is not necessary to + ## call this function explicitly. runnableExamples: - var a = initDoublyLinkedRing[int]() + let a = initDoublyLinkedRing[int]() + discard proc newDoublyLinkedNode*[T](value: T): (DoublyLinkedNode[T]) = ## Creates a new doubly linked node with the given `value`. runnableExamples: - var n = newDoublyLinkedNode[int](5) + let n = newDoublyLinkedNode[int](5) assert n.value == 5 new(result) @@ -156,28 +160,30 @@ proc newDoublyLinkedNode*[T](value: T): (DoublyLinkedNode[T]) = proc newSinglyLinkedNode*[T](value: T): (SinglyLinkedNode[T]) = ## Creates a new singly linked node with the given `value`. runnableExamples: - var n = newSinglyLinkedNode[int](5) + let n = newSinglyLinkedNode[int](5) assert n.value == 5 new(result) result.value = value func toSinglyLinkedList*[T](elems: openArray[T]): SinglyLinkedList[T] {.since: (1, 5, 1).} = - ## Creates a new `SinglyLinkedList` from members of `elems`. + ## Creates a new `SinglyLinkedList` from the members of `elems`. runnableExamples: - import std/sequtils + from std/sequtils import toSeq let a = [1, 2, 3, 4, 5].toSinglyLinkedList assert a.toSeq == [1, 2, 3, 4, 5] + result = initSinglyLinkedList[T]() for elem in elems.items: result.add(elem) func toDoublyLinkedList*[T](elems: openArray[T]): DoublyLinkedList[T] {.since: (1, 5, 1).} = - ## Creates a new `DoublyLinkedList` from members of `elems`. + ## Creates a new `DoublyLinkedList` from the members of `elems`. runnableExamples: - import std/sequtils + from std/sequtils import toSeq let a = [1, 2, 3, 4, 5].toDoublyLinkedList assert a.toSeq == [1, 2, 3, 4, 5] + result = initDoublyLinkedList[T]() for elem in elems.items: result.add(elem) @@ -199,75 +205,79 @@ template itemsRingImpl() {.dirty.} = iterator items*[T](L: SomeLinkedList[T]): T = ## Yields every value of `L`. ## - ## See also: + ## **See also:** ## * `mitems iterator <#mitems.i,SomeLinkedList[T]>`_ ## * `nodes iterator <#nodes.i,SomeLinkedList[T]>`_ runnableExamples: from std/sugar import collect from std/sequtils import toSeq let a = collect(initSinglyLinkedList): - for i in 1..3: 10*i - doAssert toSeq(items(a)) == toSeq(a) - doAssert toSeq(a) == @[10, 20, 30] + for i in 1..3: 10 * i + assert toSeq(items(a)) == toSeq(a) + assert toSeq(a) == @[10, 20, 30] + itemsListImpl() iterator items*[T](L: SomeLinkedRing[T]): T = ## Yields every value of `L`. ## - ## See also: + ## **See also:** ## * `mitems iterator <#mitems.i,SomeLinkedRing[T]>`_ ## * `nodes iterator <#nodes.i,SomeLinkedRing[T]>`_ runnableExamples: from std/sugar import collect from std/sequtils import toSeq let a = collect(initSinglyLinkedRing): - for i in 1 .. 3: 10 * i - doAssert toSeq(items(a)) == toSeq(a) - doAssert toSeq(a) == @[10, 20, 30] + for i in 1..3: 10 * i + assert toSeq(items(a)) == toSeq(a) + assert toSeq(a) == @[10, 20, 30] + itemsRingImpl() iterator mitems*[T](L: var SomeLinkedList[T]): var T = ## Yields every value of `L` so that you can modify it. ## - ## See also: + ## **See also:** ## * `items iterator <#items.i,SomeLinkedList[T]>`_ ## * `nodes iterator <#nodes.i,SomeLinkedList[T]>`_ runnableExamples: var a = initSinglyLinkedList[int]() - for i in 1 .. 5: + for i in 1..5: a.add(10 * i) assert $a == "[10, 20, 30, 40, 50]" for x in mitems(a): x = 5 * x - 1 assert $a == "[49, 99, 149, 199, 249]" + itemsListImpl() iterator mitems*[T](L: var SomeLinkedRing[T]): var T = ## Yields every value of `L` so that you can modify it. ## - ## See also: + ## **See also:** ## * `items iterator <#items.i,SomeLinkedRing[T]>`_ ## * `nodes iterator <#nodes.i,SomeLinkedRing[T]>`_ runnableExamples: var a = initSinglyLinkedRing[int]() - for i in 1 .. 5: + for i in 1..5: a.add(10 * i) assert $a == "[10, 20, 30, 40, 50]" for x in mitems(a): x = 5 * x - 1 assert $a == "[49, 99, 149, 199, 249]" + itemsRingImpl() iterator nodes*[T](L: SomeLinkedList[T]): SomeLinkedNode[T] = ## Iterates over every node of `x`. Removing the current node from the ## list during traversal is supported. ## - ## See also: + ## **See also:** ## * `items iterator <#items.i,SomeLinkedList[T]>`_ ## * `mitems iterator <#mitems.i,SomeLinkedList[T]>`_ runnableExamples: var a = initDoublyLinkedList[int]() - for i in 1 .. 5: + for i in 1..5: a.add(10 * i) assert $a == "[10, 20, 30, 40, 50]" for x in nodes(a): @@ -279,7 +289,7 @@ iterator nodes*[T](L: SomeLinkedList[T]): SomeLinkedNode[T] = var it = L.head while it != nil: - var nxt = it.next + let nxt = it.next yield it it = nxt @@ -287,12 +297,12 @@ iterator nodes*[T](L: SomeLinkedRing[T]): SomeLinkedNode[T] = ## Iterates over every node of `x`. Removing the current node from the ## list during traversal is supported. ## - ## See also: + ## **See also:** ## * `items iterator <#items.i,SomeLinkedRing[T]>`_ ## * `mitems iterator <#mitems.i,SomeLinkedRing[T]>`_ runnableExamples: var a = initDoublyLinkedRing[int]() - for i in 1 .. 5: + for i in 1..5: a.add(10 * i) assert $a == "[10, 20, 30, 40, 50]" for x in nodes(a): @@ -305,13 +315,17 @@ iterator nodes*[T](L: SomeLinkedRing[T]): SomeLinkedNode[T] = var it = L.head if it != nil: while true: - var nxt = it.next + let nxt = it.next yield it it = nxt if it == L.head: break proc `$`*[T](L: SomeLinkedCollection[T]): string = ## Turns a list into its string representation for logging and printing. + runnableExamples: + let a = [1, 2, 3, 4].toSinglyLinkedList + assert $a == "[1, 2, 3, 4]" + result = "[" for x in nodes(L): if result.len > 1: result.add(", ") @@ -322,12 +336,10 @@ proc find*[T](L: SomeLinkedCollection[T], value: T): SomeLinkedNode[T] = ## Searches in the list for a value. Returns `nil` if the value does not ## exist. ## - ## See also: + ## **See also:** ## * `contains proc <#contains,SomeLinkedCollection[T],T>`_ runnableExamples: - var a = initSinglyLinkedList[int]() - a.add(9) - a.add(8) + let a = [9, 8].toSinglyLinkedList assert a.find(9).value == 9 assert a.find(1) == nil @@ -336,14 +348,13 @@ proc find*[T](L: SomeLinkedCollection[T], value: T): SomeLinkedNode[T] = proc contains*[T](L: SomeLinkedCollection[T], value: T): bool {.inline.} = ## Searches in the list for a value. Returns `false` if the value does not - ## exist, `true` otherwise. + ## exist, `true` otherwise. This allows the usage of the `in` and `notin` + ## operators. ## - ## See also: + ## **See also:** ## * `find proc <#find,SomeLinkedCollection[T],T>`_ runnableExamples: - var a = initSinglyLinkedList[int]() - a.add(9) - a.add(8) + let a = [9, 8].toSinglyLinkedList assert a.contains(9) assert 8 in a assert(not a.contains(1)) @@ -354,21 +365,21 @@ proc contains*[T](L: SomeLinkedCollection[T], value: T): bool {.inline.} = proc prepend*[T: SomeLinkedList](a: var T, b: T) {.since: (1, 5, 1).} = ## Prepends a shallow copy of `b` to the beginning of `a`. ## - ## See also: - ## * `prependMoved proc <#prependMoved,SinglyLinkedList[T],SinglyLinkedList[T]>`_ - ## * `prependMoved proc <#prependMoved,DoublyLinkedList[T],DoublyLinkedList[T]>`_ + ## **See also:** + ## * `prependMoved proc <#prependMoved,T,T>`_ ## for moving the second list instead of copying runnableExamples: - import std/sequtils + from std/sequtils import toSeq var a = [4, 5].toSinglyLinkedList let b = [1, 2, 3].toSinglyLinkedList - a.prepend b + a.prepend(b) assert a.toSeq == [1, 2, 3, 4, 5] assert b.toSeq == [1, 2, 3] - a.prepend a + a.prepend(a) assert a.toSeq == [1, 2, 3, 4, 5, 1, 2, 3, 4, 5] + var tmp = b.copy - tmp.addMoved a + tmp.addMoved(a) a = tmp proc prependMoved*[T: SomeLinkedList](a, b: var T) {.since: (1, 5, 1).} = @@ -376,7 +387,7 @@ proc prependMoved*[T: SomeLinkedList](a, b: var T) {.since: (1, 5, 1).} = ## Note that `b` becomes empty after the operation unless it has the same address as `a`. ## Self-prepending results in a cycle. ## - ## See also: + ## **See also:** ## * `prepend proc <#prepend,T,T>`_ ## for prepending a copy of a list runnableExamples: @@ -385,33 +396,32 @@ proc prependMoved*[T: SomeLinkedList](a, b: var T) {.since: (1, 5, 1).} = a = [4, 5].toSinglyLinkedList b = [1, 2, 3].toSinglyLinkedList c = [0, 1].toSinglyLinkedList - a.prependMoved b + a.prependMoved(b) assert a.toSeq == [1, 2, 3, 4, 5] assert b.toSeq == [] - c.prependMoved c + c.prependMoved(c) let s = collect: for i, ci in enumerate(c): if i == 6: break ci assert s == [0, 1, 0, 1, 0, 1] - b.addMoved a + + b.addMoved(a) when defined(js): # XXX: swap broken in js; bug #16771 (b, a) = (a, b) else: swap a, b -proc add*[T](L: var SinglyLinkedList[T], - n: SinglyLinkedNode[T]) {.inline.} = +proc add*[T](L: var SinglyLinkedList[T], n: SinglyLinkedNode[T]) {.inline.} = ## Appends (adds to the end) a node `n` to `L`. Efficiency: O(1). ## - ## See also: + ## **See also:** ## * `add proc <#add,SinglyLinkedList[T],T>`_ for appending a value ## * `prepend proc <#prepend,SinglyLinkedList[T],SinglyLinkedNode[T]>`_ ## for prepending a node ## * `prepend proc <#prepend,SinglyLinkedList[T],T>`_ for prepending a value runnableExamples: - var - a = initSinglyLinkedList[int]() - n = newSinglyLinkedNode[int](9) + var a = initSinglyLinkedList[int]() + let n = newSinglyLinkedNode[int](9) a.add(n) assert a.contains(9) @@ -425,7 +435,7 @@ proc add*[T](L: var SinglyLinkedList[T], proc add*[T](L: var SinglyLinkedList[T], value: T) {.inline.} = ## Appends (adds to the end) a value to `L`. Efficiency: O(1). ## - ## See also: + ## **See also:** ## * `add proc <#add,SinglyLinkedList[T],T>`_ for appending a value ## * `prepend proc <#prepend,SinglyLinkedList[T],SinglyLinkedNode[T]>`_ ## for prepending a node @@ -435,21 +445,21 @@ proc add*[T](L: var SinglyLinkedList[T], value: T) {.inline.} = a.add(9) a.add(8) assert a.contains(9) + add(L, newSinglyLinkedNode(value)) proc prepend*[T](L: var SinglyLinkedList[T], n: SinglyLinkedNode[T]) {.inline.} = ## Prepends (adds to the beginning) a node to `L`. Efficiency: O(1). ## - ## See also: + ## **See also:** ## * `add proc <#add,SinglyLinkedList[T],SinglyLinkedNode[T]>`_ ## for appending a node ## * `add proc <#add,SinglyLinkedList[T],T>`_ for appending a value ## * `prepend proc <#prepend,SinglyLinkedList[T],T>`_ for prepending a value runnableExamples: - var - a = initSinglyLinkedList[int]() - n = newSinglyLinkedNode[int](9) + var a = initSinglyLinkedList[int]() + let n = newSinglyLinkedNode[int](9) a.prepend(n) assert a.contains(9) @@ -460,7 +470,7 @@ proc prepend*[T](L: var SinglyLinkedList[T], proc prepend*[T](L: var SinglyLinkedList[T], value: T) {.inline.} = ## Prepends (adds to the beginning) a node to `L`. Efficiency: O(1). ## - ## See also: + ## **See also:** ## * `add proc <#add,SinglyLinkedList[T],SinglyLinkedNode[T]>`_ ## for appending a node ## * `add proc <#add,SinglyLinkedList[T],T>`_ for appending a value @@ -471,19 +481,20 @@ proc prepend*[T](L: var SinglyLinkedList[T], value: T) {.inline.} = a.prepend(9) a.prepend(8) assert a.contains(9) + prepend(L, newSinglyLinkedNode(value)) func copy*[T](a: SinglyLinkedList[T]): SinglyLinkedList[T] {.since: (1, 5, 1).} = ## Creates a shallow copy of `a`. runnableExamples: - import std/sequtils + from std/sequtils import toSeq type Foo = ref object x: int var f = Foo(x: 1) a = [f].toSinglyLinkedList let b = a.copy - a.add [f].toSinglyLinkedList + a.add([f].toSinglyLinkedList) assert a.toSeq == [f, f] assert b.toSeq == [f] # b isn't modified... f.x = 42 @@ -492,6 +503,7 @@ func copy*[T](a: SinglyLinkedList[T]): SinglyLinkedList[T] {.since: (1, 5, 1).} let c = [1, 2, 3].toSinglyLinkedList assert $c == $c.copy + result = initSinglyLinkedList[T]() for x in a.items: result.add(x) @@ -501,24 +513,24 @@ proc addMoved*[T](a, b: var SinglyLinkedList[T]) {.since: (1, 5, 1).} = ## Note that `b` becomes empty after the operation unless it has the same address as `a`. ## Self-adding results in a cycle. ## - ## See also: - ## * `add proc <#add,T,T>`_ - ## for adding a copy of a list + ## **See also:** + ## * `add proc <#add,T,T>`_ for adding a copy of a list runnableExamples: import std/[sequtils, enumerate, sugar] var a = [1, 2, 3].toSinglyLinkedList b = [4, 5].toSinglyLinkedList c = [0, 1].toSinglyLinkedList - a.addMoved b + a.addMoved(b) assert a.toSeq == [1, 2, 3, 4, 5] assert b.toSeq == [] - c.addMoved c + c.addMoved(c) let s = collect: for i, ci in enumerate(c): if i == 6: break ci assert s == [0, 1, 0, 1, 0, 1] + if a.tail != nil: a.tail.next = b.head a.tail = b.tail @@ -531,7 +543,7 @@ proc addMoved*[T](a, b: var SinglyLinkedList[T]) {.since: (1, 5, 1).} = proc add*[T](L: var DoublyLinkedList[T], n: DoublyLinkedNode[T]) = ## Appends (adds to the end) a node `n` to `L`. Efficiency: O(1). ## - ## See also: + ## **See also:** ## * `add proc <#add,DoublyLinkedList[T],T>`_ for appending a value ## * `prepend proc <#prepend,DoublyLinkedList[T],DoublyLinkedNode[T]>`_ ## for prepending a node @@ -539,9 +551,8 @@ proc add*[T](L: var DoublyLinkedList[T], n: DoublyLinkedNode[T]) = ## * `remove proc <#remove,DoublyLinkedList[T],DoublyLinkedNode[T]>`_ ## for removing a node runnableExamples: - var - a = initDoublyLinkedList[int]() - n = newDoublyLinkedNode[int](9) + var a = initDoublyLinkedList[int]() + let n = newDoublyLinkedNode[int](9) a.add(n) assert a.contains(9) @@ -556,7 +567,7 @@ proc add*[T](L: var DoublyLinkedList[T], n: DoublyLinkedNode[T]) = proc add*[T](L: var DoublyLinkedList[T], value: T) = ## Appends (adds to the end) a value to `L`. Efficiency: O(1). ## - ## See also: + ## **See also:** ## * `add proc <#add,DoublyLinkedList[T],DoublyLinkedNode[T]>`_ ## for appending a node ## * `prepend proc <#prepend,DoublyLinkedList[T],DoublyLinkedNode[T]>`_ @@ -569,12 +580,13 @@ proc add*[T](L: var DoublyLinkedList[T], value: T) = a.add(9) a.add(8) assert a.contains(9) + add(L, newDoublyLinkedNode(value)) proc prepend*[T](L: var DoublyLinkedList[T], n: DoublyLinkedNode[T]) = ## Prepends (adds to the beginning) a node `n` to `L`. Efficiency: O(1). ## - ## See also: + ## **See also:** ## * `add proc <#add,DoublyLinkedList[T],DoublyLinkedNode[T]>`_ ## for appending a node ## * `add proc <#add,DoublyLinkedList[T],T>`_ for appending a value @@ -582,9 +594,8 @@ proc prepend*[T](L: var DoublyLinkedList[T], n: DoublyLinkedNode[T]) = ## * `remove proc <#remove,DoublyLinkedList[T],DoublyLinkedNode[T]>`_ ## for removing a node runnableExamples: - var - a = initDoublyLinkedList[int]() - n = newDoublyLinkedNode[int](9) + var a = initDoublyLinkedList[int]() + let n = newDoublyLinkedNode[int](9) a.prepend(n) assert a.contains(9) @@ -599,7 +610,7 @@ proc prepend*[T](L: var DoublyLinkedList[T], n: DoublyLinkedNode[T]) = proc prepend*[T](L: var DoublyLinkedList[T], value: T) = ## Prepends (adds to the beginning) a value to `L`. Efficiency: O(1). ## - ## See also: + ## **See also:** ## * `add proc <#add,DoublyLinkedList[T],DoublyLinkedNode[T]>`_ ## for appending a node ## * `add proc <#add,DoublyLinkedList[T],T>`_ for appending a value @@ -612,23 +623,29 @@ proc prepend*[T](L: var DoublyLinkedList[T], value: T) = a.prepend(9) a.prepend(8) assert a.contains(9) + prepend(L, newDoublyLinkedNode(value)) func copy*[T](a: DoublyLinkedList[T]): DoublyLinkedList[T] {.since: (1, 5, 1).} = ## Creates a shallow copy of `a`. runnableExamples: + from std/sequtils import toSeq type Foo = ref object x: int - var f = Foo(x: 1) - let + var + f = Foo(x: 1) a = [f].toDoublyLinkedList - b = a.copy + let b = a.copy + a.add([f].toDoublyLinkedList) + assert a.toSeq == [f, f] + assert b.toSeq == [f] # b isn't modified... f.x = 42 assert a.head.value.x == 42 - assert b.head.value.x == 42 + assert b.head.value.x == 42 # ... but the elements are not deep copied let c = [1, 2, 3].toDoublyLinkedList assert $c == $c.copy + result = initDoublyLinkedList[T]() for x in a.items: result.add(x) @@ -638,7 +655,7 @@ proc addMoved*[T](a, b: var DoublyLinkedList[T]) {.since: (1, 5, 1).} = ## Note that `b` becomes empty after the operation unless it has the same address as `a`. ## Self-adding results in a cycle. ## - ## See also: + ## **See also:** ## * `add proc <#add,T,T>`_ ## for adding a copy of a list runnableExamples: @@ -647,15 +664,16 @@ proc addMoved*[T](a, b: var DoublyLinkedList[T]) {.since: (1, 5, 1).} = a = [1, 2, 3].toDoublyLinkedList b = [4, 5].toDoublyLinkedList c = [0, 1].toDoublyLinkedList - a.addMoved b + a.addMoved(b) assert a.toSeq == [1, 2, 3, 4, 5] assert b.toSeq == [] - c.addMoved c + c.addMoved(c) let s = collect: for i, ci in enumerate(c): if i == 6: break ci assert s == [0, 1, 0, 1, 0, 1] + if b.head != nil: b.head.prev = a.tail if a.tail != nil: @@ -670,21 +688,22 @@ proc addMoved*[T](a, b: var DoublyLinkedList[T]) {.since: (1, 5, 1).} = proc add*[T: SomeLinkedList](a: var T, b: T) {.since: (1, 5, 1).} = ## Appends a shallow copy of `b` to the end of `a`. ## - ## See also: + ## **See also:** ## * `addMoved proc <#addMoved,SinglyLinkedList[T],SinglyLinkedList[T]>`_ ## * `addMoved proc <#addMoved,DoublyLinkedList[T],DoublyLinkedList[T]>`_ ## for moving the second list instead of copying runnableExamples: - import std/sequtils + from std/sequtils import toSeq var a = [1, 2, 3].toSinglyLinkedList let b = [4, 5].toSinglyLinkedList - a.add b + a.add(b) assert a.toSeq == [1, 2, 3, 4, 5] assert b.toSeq == [4, 5] - a.add a + a.add(a) assert a.toSeq == [1, 2, 3, 4, 5, 1, 2, 3, 4, 5] + var tmp = b.copy - a.addMoved tmp + a.addMoved(tmp) proc remove*[T](L: var SinglyLinkedList[T], n: SinglyLinkedNode[T]): bool {.discardable.} = ## Removes a node `n` from `L`. @@ -696,18 +715,18 @@ proc remove*[T](L: var SinglyLinkedList[T], n: SinglyLinkedNode[T]): bool {.disc import std/[sequtils, enumerate, sugar] var a = [0, 1, 2].toSinglyLinkedList let n = a.head.next - doAssert n.value == 1 - doAssert a.remove(n) == true - doAssert a.toSeq == [0, 2] - doAssert a.remove(n) == false - doAssert a.toSeq == [0, 2] - a.addMoved a # cycle: [0, 2, 0, 2, ...] - a.remove a.head + assert n.value == 1 + assert a.remove(n) == true + assert a.toSeq == [0, 2] + assert a.remove(n) == false + assert a.toSeq == [0, 2] + a.addMoved(a) # cycle: [0, 2, 0, 2, ...] + a.remove(a.head) let s = collect: for i, ai in enumerate(a): if i == 4: break ai - doAssert s == [2, 2, 2, 2] + assert s == [2, 2, 2, 2] if n == L.head: L.head = n.next @@ -731,18 +750,18 @@ proc remove*[T](L: var DoublyLinkedList[T], n: DoublyLinkedNode[T]) = import std/[sequtils, enumerate, sugar] var a = [0, 1, 2].toSinglyLinkedList let n = a.head.next - doAssert n.value == 1 - a.remove n - doAssert a.toSeq == [0, 2] - a.remove n - doAssert a.toSeq == [0, 2] - a.addMoved a # cycle: [0, 2, 0, 2, ...] - a.remove a.head + assert n.value == 1 + a.remove(n) + assert a.toSeq == [0, 2] + a.remove(n) + assert a.toSeq == [0, 2] + a.addMoved(a) # cycle: [0, 2, 0, 2, ...] + a.remove(a.head) let s = collect: for i, ai in enumerate(a): if i == 4: break ai - doAssert s == [2, 2, 2, 2] + assert s == [2, 2, 2, 2] if n == L.tail: L.tail = n.prev if n == L.head: L.head = n.next @@ -754,15 +773,14 @@ proc remove*[T](L: var DoublyLinkedList[T], n: DoublyLinkedNode[T]) = proc add*[T](L: var SinglyLinkedRing[T], n: SinglyLinkedNode[T]) = ## Appends (adds to the end) a node `n` to `L`. Efficiency: O(1). ## - ## See also: + ## **See also:** ## * `add proc <#add,SinglyLinkedRing[T],T>`_ for appending a value ## * `prepend proc <#prepend,SinglyLinkedRing[T],SinglyLinkedNode[T]>`_ ## for prepending a node ## * `prepend proc <#prepend,SinglyLinkedRing[T],T>`_ for prepending a value runnableExamples: - var - a = initSinglyLinkedRing[int]() - n = newSinglyLinkedNode[int](9) + var a = initSinglyLinkedRing[int]() + let n = newSinglyLinkedNode[int](9) a.add(n) assert a.contains(9) @@ -770,16 +788,15 @@ proc add*[T](L: var SinglyLinkedRing[T], n: SinglyLinkedNode[T]) = n.next = L.head assert(L.tail != nil) L.tail.next = n - L.tail = n else: n.next = n L.head = n - L.tail = n + L.tail = n proc add*[T](L: var SinglyLinkedRing[T], value: T) = ## Appends (adds to the end) a value to `L`. Efficiency: O(1). ## - ## See also: + ## **See also:** ## * `add proc <#add,SinglyLinkedRing[T],SinglyLinkedNode[T]>`_ ## for appending a node ## * `prepend proc <#prepend,SinglyLinkedRing[T],SinglyLinkedNode[T]>`_ @@ -790,20 +807,20 @@ proc add*[T](L: var SinglyLinkedRing[T], value: T) = a.add(9) a.add(8) assert a.contains(9) + add(L, newSinglyLinkedNode(value)) proc prepend*[T](L: var SinglyLinkedRing[T], n: SinglyLinkedNode[T]) = ## Prepends (adds to the beginning) a node `n` to `L`. Efficiency: O(1). ## - ## See also: + ## **See also:** ## * `add proc <#add,SinglyLinkedRing[T],SinglyLinkedNode[T]>`_ ## for appending a node ## * `add proc <#add,SinglyLinkedRing[T],T>`_ for appending a value ## * `prepend proc <#prepend,SinglyLinkedRing[T],T>`_ for prepending a value runnableExamples: - var - a = initSinglyLinkedRing[int]() - n = newSinglyLinkedNode[int](9) + var a = initSinglyLinkedRing[int]() + let n = newSinglyLinkedNode[int](9) a.prepend(n) assert a.contains(9) @@ -819,7 +836,7 @@ proc prepend*[T](L: var SinglyLinkedRing[T], n: SinglyLinkedNode[T]) = proc prepend*[T](L: var SinglyLinkedRing[T], value: T) = ## Prepends (adds to the beginning) a value to `L`. Efficiency: O(1). ## - ## See also: + ## **See also:** ## * `add proc <#add,SinglyLinkedRing[T],SinglyLinkedNode[T]>`_ ## for appending a node ## * `add proc <#add,SinglyLinkedRing[T],T>`_ for appending a value @@ -830,6 +847,7 @@ proc prepend*[T](L: var SinglyLinkedRing[T], value: T) = a.prepend(9) a.prepend(8) assert a.contains(9) + prepend(L, newSinglyLinkedNode(value)) @@ -837,7 +855,7 @@ proc prepend*[T](L: var SinglyLinkedRing[T], value: T) = proc add*[T](L: var DoublyLinkedRing[T], n: DoublyLinkedNode[T]) = ## Appends (adds to the end) a node `n` to `L`. Efficiency: O(1). ## - ## See also: + ## **See also:** ## * `add proc <#add,DoublyLinkedRing[T],T>`_ for appending a value ## * `prepend proc <#prepend,DoublyLinkedRing[T],DoublyLinkedNode[T]>`_ ## for prepending a node @@ -845,9 +863,8 @@ proc add*[T](L: var DoublyLinkedRing[T], n: DoublyLinkedNode[T]) = ## * `remove proc <#remove,DoublyLinkedRing[T],DoublyLinkedNode[T]>`_ ## for removing a node runnableExamples: - var - a = initDoublyLinkedRing[int]() - n = newDoublyLinkedNode[int](9) + var a = initDoublyLinkedRing[int]() + let n = newDoublyLinkedNode[int](9) a.add(n) assert a.contains(9) @@ -864,7 +881,7 @@ proc add*[T](L: var DoublyLinkedRing[T], n: DoublyLinkedNode[T]) = proc add*[T](L: var DoublyLinkedRing[T], value: T) = ## Appends (adds to the end) a value to `L`. Efficiency: O(1). ## - ## See also: + ## **See also:** ## * `add proc <#add,DoublyLinkedRing[T],DoublyLinkedNode[T]>`_ ## for appending a node ## * `prepend proc <#prepend,DoublyLinkedRing[T],DoublyLinkedNode[T]>`_ @@ -877,12 +894,13 @@ proc add*[T](L: var DoublyLinkedRing[T], value: T) = a.add(9) a.add(8) assert a.contains(9) + add(L, newDoublyLinkedNode(value)) proc prepend*[T](L: var DoublyLinkedRing[T], n: DoublyLinkedNode[T]) = ## Prepends (adds to the beginning) a node `n` to `L`. Efficiency: O(1). ## - ## See also: + ## **See also:** ## * `add proc <#add,DoublyLinkedRing[T],DoublyLinkedNode[T]>`_ ## for appending a node ## * `add proc <#add,DoublyLinkedRing[T],T>`_ for appending a value @@ -890,9 +908,8 @@ proc prepend*[T](L: var DoublyLinkedRing[T], n: DoublyLinkedNode[T]) = ## * `remove proc <#remove,DoublyLinkedRing[T],DoublyLinkedNode[T]>`_ ## for removing a node runnableExamples: - var - a = initDoublyLinkedRing[int]() - n = newDoublyLinkedNode[int](9) + var a = initDoublyLinkedRing[int]() + let n = newDoublyLinkedNode[int](9) a.prepend(n) assert a.contains(9) @@ -909,7 +926,7 @@ proc prepend*[T](L: var DoublyLinkedRing[T], n: DoublyLinkedNode[T]) = proc prepend*[T](L: var DoublyLinkedRing[T], value: T) = ## Prepends (adds to the beginning) a value to `L`. Efficiency: O(1). ## - ## See also: + ## **See also:** ## * `add proc <#add,DoublyLinkedRing[T],DoublyLinkedNode[T]>`_ ## for appending a node ## * `add proc <#add,DoublyLinkedRing[T],T>`_ for appending a value @@ -922,14 +939,16 @@ proc prepend*[T](L: var DoublyLinkedRing[T], value: T) = a.prepend(9) a.prepend(8) assert a.contains(9) + prepend(L, newDoublyLinkedNode(value)) proc remove*[T](L: var DoublyLinkedRing[T], n: DoublyLinkedNode[T]) = ## Removes `n` from `L`. Efficiency: O(1). + ## This function assumes, for the sake of efficiency, that `n` is contained in `L`, + ## otherwise the effects are undefined. runnableExamples: - var - a = initDoublyLinkedRing[int]() - n = newDoublyLinkedNode[int](5) + var a = initDoublyLinkedRing[int]() + let n = newDoublyLinkedNode[int](5) a.add(n) assert 5 in a a.remove(n) @@ -938,37 +957,37 @@ proc remove*[T](L: var DoublyLinkedRing[T], n: DoublyLinkedNode[T]) = n.next.prev = n.prev n.prev.next = n.next if n == L.head: - var p = L.head.prev + let p = L.head.prev if p == L.head: # only one element left: L.head = nil else: - L.head = L.head.prev + L.head = p proc append*[T](a: var (SinglyLinkedList[T] | SinglyLinkedRing[T]), b: SinglyLinkedList[T] | SinglyLinkedNode[T] | T) = ## Alias for `a.add(b)`. ## - ## See also: + ## **See also:** ## * `add proc <#add,SinglyLinkedList[T],SinglyLinkedNode[T]>`_ ## * `add proc <#add,SinglyLinkedList[T],T>`_ ## * `add proc <#add,T,T>`_ - a.add b + a.add(b) proc append*[T](a: var (DoublyLinkedList[T] | DoublyLinkedRing[T]), b: DoublyLinkedList[T] | DoublyLinkedNode[T] | T) = ## Alias for `a.add(b)`. ## - ## See also: + ## **See also:** ## * `add proc <#add,DoublyLinkedList[T],DoublyLinkedNode[T]>`_ ## * `add proc <#add,DoublyLinkedList[T],T>`_ ## * `add proc <#add,T,T>`_ - a.add b + a.add(b) proc appendMoved*[T: SomeLinkedList](a, b: var T) {.since: (1, 5, 1).} = ## Alias for `a.addMoved(b)`. ## - ## See also: + ## **See also:** ## * `addMoved proc <#addMoved,SinglyLinkedList[T],SinglyLinkedList[T]>`_ ## * `addMoved proc <#addMoved,DoublyLinkedList[T],DoublyLinkedList[T]>`_ - a.addMoved b + a.addMoved(b)