Improve the lists module (#17312)
This commit is contained in:
parent
58e88dbf12
commit
b52febf77e
1 changed files with 185 additions and 166 deletions
|
|
@ -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)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue