Initialized collections (#11094)
* tables: initialized by default * sets: initialized by default * DRY: extract shared functionality * add a changelog entry * fix errors * don't test include files * make it work for sharedtables * fix discovered bugs * add exhaustive tests
This commit is contained in:
parent
55aa2129b5
commit
737fff5902
8 changed files with 660 additions and 422 deletions
|
|
@ -237,9 +237,13 @@ type
|
|||
## For creating a new empty TableRef, use `newTable proc
|
||||
## <#newTable,int>`_.
|
||||
|
||||
const
|
||||
defaultInitialSize* = 64
|
||||
|
||||
# ------------------------------ helpers ---------------------------------
|
||||
|
||||
# Do NOT move these to tableimpl.nim, because sharedtables uses that
|
||||
# file and has its own implementation.
|
||||
template maxHash(t): untyped = high(t.data)
|
||||
template dataLen(t): untyped = len(t.data)
|
||||
|
||||
|
|
@ -260,30 +264,6 @@ template get(t, key): untyped =
|
|||
else:
|
||||
raise newException(KeyError, "key not found")
|
||||
|
||||
template getOrDefaultImpl(t, key): untyped =
|
||||
mixin rawGet
|
||||
var hc: Hash
|
||||
var index = rawGet(t, key, hc)
|
||||
if index >= 0: result = t.data[index].val
|
||||
|
||||
template getOrDefaultImpl(t, key, default: untyped): untyped =
|
||||
mixin rawGet
|
||||
var hc: Hash
|
||||
var index = rawGet(t, key, hc)
|
||||
result = if index >= 0: t.data[index].val else: default
|
||||
|
||||
template dollarImpl(): untyped {.dirty.} =
|
||||
if t.len == 0:
|
||||
result = "{:}"
|
||||
else:
|
||||
result = "{"
|
||||
for key, val in pairs(t):
|
||||
if result.len > 1: result.add(", ")
|
||||
result.addQuoted(key)
|
||||
result.add(": ")
|
||||
result.addQuoted(val)
|
||||
result.add("}")
|
||||
|
||||
proc enlarge[A, B](t: var Table[A, B]) =
|
||||
var n: KeyValuePairSeq[A, B]
|
||||
newSeq(n, len(t.data) * growthFactor)
|
||||
|
|
@ -296,14 +276,6 @@ proc enlarge[A, B](t: var Table[A, B]) =
|
|||
j = nextTry(j, maxHash(t))
|
||||
rawInsert(t, t.data, n[i].key, n[i].val, eh, j)
|
||||
|
||||
template equalsImpl(s, t: typed): typed =
|
||||
if s.counter == t.counter:
|
||||
# different insertion orders mean different 'data' seqs, so we have
|
||||
# to use the slow route here:
|
||||
for key, val in s:
|
||||
if not t.hasKey(key): return false
|
||||
if t.getOrDefault(key) != val: return false
|
||||
return true
|
||||
|
||||
|
||||
|
||||
|
|
@ -311,7 +283,7 @@ template equalsImpl(s, t: typed): typed =
|
|||
# ------------------------------ Table ------------------------------
|
||||
# -------------------------------------------------------------------
|
||||
|
||||
proc initTable*[A, B](initialSize=64): Table[A, B] =
|
||||
proc initTable*[A, B](initialsize = defaultInitialSize): Table[A, B] =
|
||||
## Creates a new hash table that is empty.
|
||||
##
|
||||
## ``initialSize`` must be a power of two (default: 64).
|
||||
|
|
@ -320,6 +292,9 @@ proc initTable*[A, B](initialSize=64): Table[A, B] =
|
|||
## `math module<math.html>`_ or the `rightSize proc<#rightSize,Natural>`_
|
||||
## from this module.
|
||||
##
|
||||
## Starting from Nim v0.20, tables are initialized by default and it is
|
||||
## not necessary to call this function explicitly.
|
||||
##
|
||||
## See also:
|
||||
## * `toTable proc<#toTable,openArray[]>`_
|
||||
## * `newTable proc<#newTable,int>`_ for creating a `TableRef`
|
||||
|
|
@ -327,9 +302,7 @@ proc initTable*[A, B](initialSize=64): Table[A, B] =
|
|||
let
|
||||
a = initTable[int, string]()
|
||||
b = initTable[char, seq[int]]()
|
||||
assert isPowerOfTwo(initialSize)
|
||||
result.counter = 0
|
||||
newSeq(result.data, initialSize)
|
||||
initImpl(result, initialSize)
|
||||
|
||||
proc toTable*[A, B](pairs: openArray[(A, B)]): Table[A, B] =
|
||||
## Creates a new hash table that contains the given ``pairs``.
|
||||
|
|
@ -343,6 +316,7 @@ proc toTable*[A, B](pairs: openArray[(A, B)]): Table[A, B] =
|
|||
let a = [('a', 5), ('b', 9)]
|
||||
let b = toTable(a)
|
||||
assert b == {'a': 5, 'b': 9}.toTable
|
||||
|
||||
result = initTable[A, B](rightSize(pairs.len))
|
||||
for key, val in items(pairs): result[key] = val
|
||||
|
||||
|
|
@ -398,6 +372,7 @@ proc `[]=`*[A, B](t: var Table[A, B], key: A, val: B) =
|
|||
a['x'] = 7
|
||||
a['y'] = 33
|
||||
doAssert a == {'x': 7, 'y': 33}.toTable
|
||||
|
||||
putImpl(enlarge)
|
||||
|
||||
proc hasKey*[A, B](t: Table[A, B], key: A): bool =
|
||||
|
|
@ -414,6 +389,7 @@ proc hasKey*[A, B](t: Table[A, B], key: A): bool =
|
|||
let a = {'a': 5, 'b': 9}.toTable
|
||||
doAssert a.hasKey('a') == true
|
||||
doAssert a.hasKey('z') == false
|
||||
|
||||
var hc: Hash
|
||||
result = rawGet(t, key, hc) >= 0
|
||||
|
||||
|
|
@ -424,6 +400,7 @@ proc contains*[A, B](t: Table[A, B], key: A): bool =
|
|||
let a = {'a': 5, 'b': 9}.toTable
|
||||
doAssert 'b' in a == true
|
||||
doAssert a.contains('z') == false
|
||||
|
||||
return hasKey[A, B](t, key)
|
||||
|
||||
proc hasKeyOrPut*[A, B](t: var Table[A, B], key: A, val: B): bool =
|
||||
|
|
@ -443,6 +420,7 @@ proc hasKeyOrPut*[A, B](t: var Table[A, B], key: A, val: B): bool =
|
|||
if a.hasKeyOrPut('z', 50):
|
||||
a['z'] = 99
|
||||
doAssert a == {'a': 99, 'b': 9, 'z': 50}.toTable
|
||||
|
||||
hasKeyOrPutImpl(enlarge)
|
||||
|
||||
proc getOrDefault*[A, B](t: Table[A, B], key: A): B =
|
||||
|
|
@ -461,6 +439,7 @@ proc getOrDefault*[A, B](t: Table[A, B], key: A): B =
|
|||
let a = {'a': 5, 'b': 9}.toTable
|
||||
doAssert a.getOrDefault('a') == 5
|
||||
doAssert a.getOrDefault('z') == 0
|
||||
|
||||
getOrDefaultImpl(t, key)
|
||||
|
||||
proc getOrDefault*[A, B](t: Table[A, B], key: A, default: B): B =
|
||||
|
|
@ -478,6 +457,7 @@ proc getOrDefault*[A, B](t: Table[A, B], key: A, default: B): B =
|
|||
let a = {'a': 5, 'b': 9}.toTable
|
||||
doAssert a.getOrDefault('a', 99) == 5
|
||||
doAssert a.getOrDefault('z', 99) == 99
|
||||
|
||||
getOrDefaultImpl(t, key, default)
|
||||
|
||||
proc mgetOrPut*[A, B](t: var Table[A, B], key: A, val: B): var B =
|
||||
|
|
@ -497,6 +477,7 @@ proc mgetOrPut*[A, B](t: var Table[A, B], key: A, val: B): var B =
|
|||
doAssert a.mgetOrPut('a', 99) == 5
|
||||
doAssert a.mgetOrPut('z', 99) == 99
|
||||
doAssert a == {'a': 5, 'b': 9, 'z': 99}.toTable
|
||||
|
||||
mgetOrPutImpl(enlarge)
|
||||
|
||||
proc len*[A, B](t: Table[A, B]): int =
|
||||
|
|
@ -504,6 +485,7 @@ proc len*[A, B](t: Table[A, B]): int =
|
|||
runnableExamples:
|
||||
let a = {'a': 5, 'b': 9}.toTable
|
||||
doAssert len(a) == 2
|
||||
|
||||
result = t.counter
|
||||
|
||||
proc add*[A, B](t: var Table[A, B], key: A, val: B) =
|
||||
|
|
@ -527,6 +509,7 @@ proc del*[A, B](t: var Table[A, B], key: A) =
|
|||
doAssert a == {'b': 9, 'c': 13}.toTable
|
||||
a.del('z')
|
||||
doAssert a == {'b': 9, 'c': 13}.toTable
|
||||
|
||||
delImpl()
|
||||
|
||||
proc take*[A, B](t: var Table[A, B], key: A, val: var B): bool =
|
||||
|
|
@ -568,6 +551,7 @@ proc clear*[A, B](t: var Table[A, B]) =
|
|||
doAssert len(a) == 3
|
||||
clear(a)
|
||||
doAssert len(a) == 0
|
||||
|
||||
clearImpl()
|
||||
|
||||
proc `$`*[A, B](t: Table[A, B]): string =
|
||||
|
|
@ -583,6 +567,7 @@ proc `==`*[A, B](s, t: Table[A, B]): bool =
|
|||
a = {'a': 5, 'b': 9, 'c': 13}.toTable
|
||||
b = {'b': 9, 'c': 13, 'a': 5}.toTable
|
||||
doAssert a == b
|
||||
|
||||
equalsImpl(s, t)
|
||||
|
||||
proc rightSize*(count: Natural): int {.inline.} =
|
||||
|
|
@ -692,6 +677,7 @@ iterator mpairs*[A, B](t: var Table[A, B]): (A, var B) =
|
|||
for k, v in a.mpairs:
|
||||
v.add(v[0] + 10)
|
||||
doAssert a == {'e': @[2, 4, 6, 8, 12], 'o': @[1, 5, 7, 9, 11]}.toTable
|
||||
|
||||
for h in 0..high(t.data):
|
||||
if isFilled(t.data[h].hcode): yield (t.data[h].key, t.data[h].val)
|
||||
|
||||
|
|
@ -709,6 +695,7 @@ iterator keys*[A, B](t: Table[A, B]): A =
|
|||
for k in a.keys:
|
||||
a[k].add(99)
|
||||
doAssert a == {'e': @[2, 4, 6, 8, 99], 'o': @[1, 5, 7, 9, 99]}.toTable
|
||||
|
||||
for h in 0..high(t.data):
|
||||
if isFilled(t.data[h].hcode): yield t.data[h].key
|
||||
|
||||
|
|
@ -726,6 +713,7 @@ iterator values*[A, B](t: Table[A, B]): B =
|
|||
}.toTable
|
||||
for v in a.values:
|
||||
doAssert v.len == 4
|
||||
|
||||
for h in 0..high(t.data):
|
||||
if isFilled(t.data[h].hcode): yield t.data[h].val
|
||||
|
||||
|
|
@ -744,6 +732,7 @@ iterator mvalues*[A, B](t: var Table[A, B]): var B =
|
|||
for v in a.mvalues:
|
||||
v.add(99)
|
||||
doAssert a == {'e': @[2, 4, 6, 8, 99], 'o': @[1, 5, 7, 9, 99]}.toTable
|
||||
|
||||
for h in 0..high(t.data):
|
||||
if isFilled(t.data[h].hcode): yield t.data[h].val
|
||||
|
||||
|
|
@ -779,7 +768,7 @@ iterator allValues*[A, B](t: Table[A, B]; key: A): B =
|
|||
# -------------------------------------------------------------------
|
||||
|
||||
|
||||
proc newTable*[A, B](initialSize=64): TableRef[A, B] =
|
||||
proc newTable*[A, B](initialsize = defaultInitialSize): TableRef[A, B] =
|
||||
## Creates a new ref hash table that is empty.
|
||||
##
|
||||
## ``initialSize`` must be a power of two (default: 64).
|
||||
|
|
@ -796,6 +785,7 @@ proc newTable*[A, B](initialSize=64): TableRef[A, B] =
|
|||
let
|
||||
a = newTable[int, string]()
|
||||
b = newTable[char, seq[int]]()
|
||||
|
||||
new(result)
|
||||
result[] = initTable[A, B](initialSize)
|
||||
|
||||
|
|
@ -811,6 +801,7 @@ proc newTable*[A, B](pairs: openArray[(A, B)]): TableRef[A, B] =
|
|||
let a = [('a', 5), ('b', 9)]
|
||||
let b = newTable(a)
|
||||
assert b == {'a': 5, 'b': 9}.newTable
|
||||
|
||||
new(result)
|
||||
result[] = toTable[A, B](pairs)
|
||||
|
||||
|
|
@ -842,6 +833,7 @@ proc `[]`*[A, B](t: TableRef[A, B], key: A): var B =
|
|||
doAssert a['a'] == 5
|
||||
doAssertRaises(KeyError):
|
||||
echo a['z']
|
||||
|
||||
result = t[][key]
|
||||
|
||||
proc `[]=`*[A, B](t: TableRef[A, B], key: A, val: B) =
|
||||
|
|
@ -857,6 +849,7 @@ proc `[]=`*[A, B](t: TableRef[A, B], key: A, val: B) =
|
|||
a['x'] = 7
|
||||
a['y'] = 33
|
||||
doAssert a == {'x': 7, 'y': 33}.newTable
|
||||
|
||||
t[][key] = val
|
||||
|
||||
proc hasKey*[A, B](t: TableRef[A, B], key: A): bool =
|
||||
|
|
@ -874,6 +867,7 @@ proc hasKey*[A, B](t: TableRef[A, B], key: A): bool =
|
|||
let a = {'a': 5, 'b': 9}.newTable
|
||||
doAssert a.hasKey('a') == true
|
||||
doAssert a.hasKey('z') == false
|
||||
|
||||
result = t[].hasKey(key)
|
||||
|
||||
proc contains*[A, B](t: TableRef[A, B], key: A): bool =
|
||||
|
|
@ -883,6 +877,7 @@ proc contains*[A, B](t: TableRef[A, B], key: A): bool =
|
|||
let a = {'a': 5, 'b': 9}.newTable
|
||||
doAssert 'b' in a == true
|
||||
doAssert a.contains('z') == false
|
||||
|
||||
return hasKey[A, B](t, key)
|
||||
|
||||
proc hasKeyOrPut*[A, B](t: var TableRef[A, B], key: A, val: B): bool =
|
||||
|
|
@ -902,6 +897,7 @@ proc hasKeyOrPut*[A, B](t: var TableRef[A, B], key: A, val: B): bool =
|
|||
if a.hasKeyOrPut('z', 50):
|
||||
a['z'] = 99
|
||||
doAssert a == {'a': 99, 'b': 9, 'z': 50}.newTable
|
||||
|
||||
t[].hasKeyOrPut(key, val)
|
||||
|
||||
proc getOrDefault*[A, B](t: TableRef[A, B], key: A): B =
|
||||
|
|
@ -920,6 +916,7 @@ proc getOrDefault*[A, B](t: TableRef[A, B], key: A): B =
|
|||
let a = {'a': 5, 'b': 9}.newTable
|
||||
doAssert a.getOrDefault('a') == 5
|
||||
doAssert a.getOrDefault('z') == 0
|
||||
|
||||
getOrDefault(t[], key)
|
||||
|
||||
proc getOrDefault*[A, B](t: TableRef[A, B], key: A, default: B): B =
|
||||
|
|
@ -937,6 +934,7 @@ proc getOrDefault*[A, B](t: TableRef[A, B], key: A, default: B): B =
|
|||
let a = {'a': 5, 'b': 9}.newTable
|
||||
doAssert a.getOrDefault('a', 99) == 5
|
||||
doAssert a.getOrDefault('z', 99) == 99
|
||||
|
||||
getOrDefault(t[], key, default)
|
||||
|
||||
proc mgetOrPut*[A, B](t: TableRef[A, B], key: A, val: B): var B =
|
||||
|
|
@ -956,6 +954,7 @@ proc mgetOrPut*[A, B](t: TableRef[A, B], key: A, val: B): var B =
|
|||
doAssert a.mgetOrPut('a', 99) == 5
|
||||
doAssert a.mgetOrPut('z', 99) == 99
|
||||
doAssert a == {'a': 5, 'b': 9, 'z': 99}.newTable
|
||||
|
||||
t[].mgetOrPut(key, val)
|
||||
|
||||
proc len*[A, B](t: TableRef[A, B]): int =
|
||||
|
|
@ -963,6 +962,7 @@ proc len*[A, B](t: TableRef[A, B]): int =
|
|||
runnableExamples:
|
||||
let a = {'a': 5, 'b': 9}.newTable
|
||||
doAssert len(a) == 2
|
||||
|
||||
result = t.counter
|
||||
|
||||
proc add*[A, B](t: TableRef[A, B], key: A, val: B) =
|
||||
|
|
@ -988,6 +988,7 @@ proc del*[A, B](t: TableRef[A, B], key: A) =
|
|||
doAssert a == {'b': 9, 'c': 13}.newTable
|
||||
a.del('z')
|
||||
doAssert a == {'b': 9, 'c': 13}.newTable
|
||||
|
||||
t[].del(key)
|
||||
|
||||
proc take*[A, B](t: TableRef[A, B], key: A, val: var B): bool =
|
||||
|
|
@ -1012,6 +1013,7 @@ proc take*[A, B](t: TableRef[A, B], key: A, val: var B): bool =
|
|||
doAssert a.take('z', i) == false
|
||||
doAssert a == {'a': 5, 'c': 13}.newTable
|
||||
doAssert i == 0
|
||||
|
||||
result = t[].take(key, val)
|
||||
|
||||
proc clear*[A, B](t: TableRef[A, B]) =
|
||||
|
|
@ -1025,6 +1027,7 @@ proc clear*[A, B](t: TableRef[A, B]) =
|
|||
doAssert len(a) == 3
|
||||
clear(a)
|
||||
doAssert len(a) == 0
|
||||
|
||||
clearImpl()
|
||||
|
||||
proc `$`*[A, B](t: TableRef[A, B]): string =
|
||||
|
|
@ -1041,6 +1044,7 @@ proc `==`*[A, B](s, t: TableRef[A, B]): bool =
|
|||
a = {'a': 5, 'b': 9, 'c': 13}.newTable
|
||||
b = {'b': 9, 'c': 13, 'a': 5}.newTable
|
||||
doAssert a == b
|
||||
|
||||
if isNil(s): result = isNil(t)
|
||||
elif isNil(t): result = false
|
||||
else: equalsImpl(s[], t[])
|
||||
|
|
@ -1089,6 +1093,7 @@ iterator mpairs*[A, B](t: TableRef[A, B]): (A, var B) =
|
|||
for k, v in a.mpairs:
|
||||
v.add(v[0] + 10)
|
||||
doAssert a == {'e': @[2, 4, 6, 8, 12], 'o': @[1, 5, 7, 9, 11]}.newTable
|
||||
|
||||
for h in 0..high(t.data):
|
||||
if isFilled(t.data[h].hcode): yield (t.data[h].key, t.data[h].val)
|
||||
|
||||
|
|
@ -1106,6 +1111,7 @@ iterator keys*[A, B](t: TableRef[A, B]): A =
|
|||
for k in a.keys:
|
||||
a[k].add(99)
|
||||
doAssert a == {'e': @[2, 4, 6, 8, 99], 'o': @[1, 5, 7, 9, 99]}.newTable
|
||||
|
||||
for h in 0..high(t.data):
|
||||
if isFilled(t.data[h].hcode): yield t.data[h].key
|
||||
|
||||
|
|
@ -1123,6 +1129,7 @@ iterator values*[A, B](t: TableRef[A, B]): B =
|
|||
}.newTable
|
||||
for v in a.values:
|
||||
doAssert v.len == 4
|
||||
|
||||
for h in 0..high(t.data):
|
||||
if isFilled(t.data[h].hcode): yield t.data[h].val
|
||||
|
||||
|
|
@ -1140,6 +1147,7 @@ iterator mvalues*[A, B](t: TableRef[A, B]): var B =
|
|||
for v in a.mvalues:
|
||||
v.add(99)
|
||||
doAssert a == {'e': @[2, 4, 6, 8, 99], 'o': @[1, 5, 7, 9, 99]}.newTable
|
||||
|
||||
for h in 0..high(t.data):
|
||||
if isFilled(t.data[h].hcode): yield t.data[h].val
|
||||
|
||||
|
|
@ -1218,7 +1226,7 @@ template forAllOrderedPairs(yieldStmt: untyped): typed {.dirty.} =
|
|||
|
||||
# ----------------------------------------------------------------------
|
||||
|
||||
proc initOrderedTable*[A, B](initialSize=64): OrderedTable[A, B] =
|
||||
proc initOrderedTable*[A, B](initialsize = defaultInitialSize): OrderedTable[A, B] =
|
||||
## Creates a new ordered hash table that is empty.
|
||||
##
|
||||
## ``initialSize`` must be a power of two (default: 64).
|
||||
|
|
@ -1227,6 +1235,9 @@ proc initOrderedTable*[A, B](initialSize=64): OrderedTable[A, B] =
|
|||
## `math module<math.html>`_ or the `rightSize proc<#rightSize,Natural>`_
|
||||
## from this module.
|
||||
##
|
||||
## Starting from Nim v0.20, tables are initialized by default and it is
|
||||
## not necessary to call this function explicitly.
|
||||
##
|
||||
## See also:
|
||||
## * `toOrderedTable proc<#toOrderedTable,openArray[]>`_
|
||||
## * `newOrderedTable proc<#newOrderedTable,int>`_ for creating an
|
||||
|
|
@ -1235,11 +1246,9 @@ proc initOrderedTable*[A, B](initialSize=64): OrderedTable[A, B] =
|
|||
let
|
||||
a = initOrderedTable[int, string]()
|
||||
b = initOrderedTable[char, seq[int]]()
|
||||
assert isPowerOfTwo(initialSize)
|
||||
result.counter = 0
|
||||
initImpl(result, initialSize)
|
||||
result.first = -1
|
||||
result.last = -1
|
||||
newSeq(result.data, initialSize)
|
||||
|
||||
proc toOrderedTable*[A, B](pairs: openArray[(A, B)]): OrderedTable[A, B] =
|
||||
## Creates a new ordered hash table that contains the given ``pairs``.
|
||||
|
|
@ -1254,6 +1263,7 @@ proc toOrderedTable*[A, B](pairs: openArray[(A, B)]): OrderedTable[A, B] =
|
|||
let a = [('a', 5), ('b', 9)]
|
||||
let b = toOrderedTable(a)
|
||||
assert b == {'a': 5, 'b': 9}.toOrderedTable
|
||||
|
||||
result = initOrderedTable[A, B](rightSize(pairs.len))
|
||||
for key, val in items(pairs): result[key] = val
|
||||
|
||||
|
|
@ -1278,6 +1288,7 @@ proc `[]`*[A, B](t: OrderedTable[A, B], key: A): B =
|
|||
doAssert a['a'] == 5
|
||||
doAssertRaises(KeyError):
|
||||
echo a['z']
|
||||
|
||||
get(t, key)
|
||||
|
||||
proc `[]`*[A, B](t: var OrderedTable[A, B], key: A): var B=
|
||||
|
|
@ -1309,6 +1320,7 @@ proc `[]=`*[A, B](t: var OrderedTable[A, B], key: A, val: B) =
|
|||
a['x'] = 7
|
||||
a['y'] = 33
|
||||
doAssert a == {'x': 7, 'y': 33}.toOrderedTable
|
||||
|
||||
putImpl(enlarge)
|
||||
|
||||
proc hasKey*[A, B](t: OrderedTable[A, B], key: A): bool =
|
||||
|
|
@ -1326,6 +1338,7 @@ proc hasKey*[A, B](t: OrderedTable[A, B], key: A): bool =
|
|||
let a = {'a': 5, 'b': 9}.toOrderedTable
|
||||
doAssert a.hasKey('a') == true
|
||||
doAssert a.hasKey('z') == false
|
||||
|
||||
var hc: Hash
|
||||
result = rawGet(t, key, hc) >= 0
|
||||
|
||||
|
|
@ -1336,6 +1349,7 @@ proc contains*[A, B](t: OrderedTable[A, B], key: A): bool =
|
|||
let a = {'a': 5, 'b': 9}.toOrderedTable
|
||||
doAssert 'b' in a == true
|
||||
doAssert a.contains('z') == false
|
||||
|
||||
return hasKey[A, B](t, key)
|
||||
|
||||
proc hasKeyOrPut*[A, B](t: var OrderedTable[A, B], key: A, val: B): bool =
|
||||
|
|
@ -1355,6 +1369,7 @@ proc hasKeyOrPut*[A, B](t: var OrderedTable[A, B], key: A, val: B): bool =
|
|||
if a.hasKeyOrPut('z', 50):
|
||||
a['z'] = 99
|
||||
doAssert a == {'a': 99, 'b': 9, 'z': 50}.toOrderedTable
|
||||
|
||||
hasKeyOrPutImpl(enlarge)
|
||||
|
||||
proc getOrDefault*[A, B](t: OrderedTable[A, B], key: A): B =
|
||||
|
|
@ -1373,6 +1388,7 @@ proc getOrDefault*[A, B](t: OrderedTable[A, B], key: A): B =
|
|||
let a = {'a': 5, 'b': 9}.toOrderedTable
|
||||
doAssert a.getOrDefault('a') == 5
|
||||
doAssert a.getOrDefault('z') == 0
|
||||
|
||||
getOrDefaultImpl(t, key)
|
||||
|
||||
proc getOrDefault*[A, B](t: OrderedTable[A, B], key: A, default: B): B =
|
||||
|
|
@ -1390,6 +1406,7 @@ proc getOrDefault*[A, B](t: OrderedTable[A, B], key: A, default: B): B =
|
|||
let a = {'a': 5, 'b': 9}.toOrderedTable
|
||||
doAssert a.getOrDefault('a', 99) == 5
|
||||
doAssert a.getOrDefault('z', 99) == 99
|
||||
|
||||
getOrDefaultImpl(t, key, default)
|
||||
|
||||
proc mgetOrPut*[A, B](t: var OrderedTable[A, B], key: A, val: B): var B =
|
||||
|
|
@ -1409,6 +1426,7 @@ proc mgetOrPut*[A, B](t: var OrderedTable[A, B], key: A, val: B): var B =
|
|||
doAssert a.mgetOrPut('a', 99) == 5
|
||||
doAssert a.mgetOrPut('z', 99) == 99
|
||||
doAssert a == {'a': 5, 'b': 9, 'z': 99}.toOrderedTable
|
||||
|
||||
mgetOrPutImpl(enlarge)
|
||||
|
||||
proc len*[A, B](t: OrderedTable[A, B]): int {.inline.} =
|
||||
|
|
@ -1416,6 +1434,7 @@ proc len*[A, B](t: OrderedTable[A, B]): int {.inline.} =
|
|||
runnableExamples:
|
||||
let a = {'a': 5, 'b': 9}.toOrderedTable
|
||||
doAssert len(a) == 2
|
||||
|
||||
result = t.counter
|
||||
|
||||
proc add*[A, B](t: var OrderedTable[A, B], key: A, val: B) =
|
||||
|
|
@ -1440,6 +1459,7 @@ proc del*[A, B](t: var OrderedTable[A, B], key: A) =
|
|||
doAssert a == {'b': 9, 'c': 13}.toOrderedTable
|
||||
a.del('z')
|
||||
doAssert a == {'b': 9, 'c': 13}.toOrderedTable
|
||||
|
||||
var n: OrderedKeyValuePairSeq[A, B]
|
||||
newSeq(n, len(t.data))
|
||||
var h = t.first
|
||||
|
|
@ -1467,6 +1487,7 @@ proc clear*[A, B](t: var OrderedTable[A, B]) =
|
|||
doAssert len(a) == 3
|
||||
clear(a)
|
||||
doAssert len(a) == 0
|
||||
|
||||
clearImpl()
|
||||
t.first = -1
|
||||
t.last = -1
|
||||
|
|
@ -1602,6 +1623,7 @@ iterator mpairs*[A, B](t: var OrderedTable[A, B]): (A, var B) =
|
|||
for k, v in a.mpairs:
|
||||
v.add(v[0] + 10)
|
||||
doAssert a == {'o': @[1, 5, 7, 9, 11], 'e': @[2, 4, 6, 8, 12]}.toOrderedTable
|
||||
|
||||
forAllOrderedPairs:
|
||||
yield (t.data[h].key, t.data[h].val)
|
||||
|
||||
|
|
@ -1619,6 +1641,7 @@ iterator keys*[A, B](t: OrderedTable[A, B]): A =
|
|||
for k in a.keys:
|
||||
a[k].add(99)
|
||||
doAssert a == {'o': @[1, 5, 7, 9, 99], 'e': @[2, 4, 6, 8, 99]}.toOrderedTable
|
||||
|
||||
forAllOrderedPairs:
|
||||
yield t.data[h].key
|
||||
|
||||
|
|
@ -1636,6 +1659,7 @@ iterator values*[A, B](t: OrderedTable[A, B]): B =
|
|||
}.toOrderedTable
|
||||
for v in a.values:
|
||||
doAssert v.len == 4
|
||||
|
||||
forAllOrderedPairs:
|
||||
yield t.data[h].val
|
||||
|
||||
|
|
@ -1666,7 +1690,7 @@ iterator mvalues*[A, B](t: var OrderedTable[A, B]): var B =
|
|||
# --------------------------- OrderedTableRef -------------------------------
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
proc newOrderedTable*[A, B](initialSize=64): OrderedTableRef[A, B] =
|
||||
proc newOrderedTable*[A, B](initialsize = defaultInitialSize): OrderedTableRef[A, B] =
|
||||
## Creates a new ordered ref hash table that is empty.
|
||||
##
|
||||
## ``initialSize`` must be a power of two (default: 64).
|
||||
|
|
@ -1700,6 +1724,7 @@ proc newOrderedTable*[A, B](pairs: openArray[(A, B)]): OrderedTableRef[A, B] =
|
|||
let a = [('a', 5), ('b', 9)]
|
||||
let b = newOrderedTable(a)
|
||||
assert b == {'a': 5, 'b': 9}.newOrderedTable
|
||||
|
||||
result = newOrderedTable[A, B](rightSize(pairs.len))
|
||||
for key, val in items(pairs): result.add(key, val)
|
||||
|
||||
|
|
@ -1740,6 +1765,7 @@ proc `[]=`*[A, B](t: OrderedTableRef[A, B], key: A, val: B) =
|
|||
a['x'] = 7
|
||||
a['y'] = 33
|
||||
doAssert a == {'x': 7, 'y': 33}.newOrderedTable
|
||||
|
||||
t[][key] = val
|
||||
|
||||
proc hasKey*[A, B](t: OrderedTableRef[A, B], key: A): bool =
|
||||
|
|
@ -1757,6 +1783,7 @@ proc hasKey*[A, B](t: OrderedTableRef[A, B], key: A): bool =
|
|||
let a = {'a': 5, 'b': 9}.newOrderedTable
|
||||
doAssert a.hasKey('a') == true
|
||||
doAssert a.hasKey('z') == false
|
||||
|
||||
result = t[].hasKey(key)
|
||||
|
||||
proc contains*[A, B](t: OrderedTableRef[A, B], key: A): bool =
|
||||
|
|
@ -1766,6 +1793,7 @@ proc contains*[A, B](t: OrderedTableRef[A, B], key: A): bool =
|
|||
let a = {'a': 5, 'b': 9}.newOrderedTable
|
||||
doAssert 'b' in a == true
|
||||
doAssert a.contains('z') == false
|
||||
|
||||
return hasKey[A, B](t, key)
|
||||
|
||||
proc hasKeyOrPut*[A, B](t: var OrderedTableRef[A, B], key: A, val: B): bool =
|
||||
|
|
@ -1785,6 +1813,7 @@ proc hasKeyOrPut*[A, B](t: var OrderedTableRef[A, B], key: A, val: B): bool =
|
|||
if a.hasKeyOrPut('z', 50):
|
||||
a['z'] = 99
|
||||
doAssert a == {'a': 99, 'b': 9, 'z': 50}.newOrderedTable
|
||||
|
||||
result = t[].hasKeyOrPut(key, val)
|
||||
|
||||
proc getOrDefault*[A, B](t: OrderedTableRef[A, B], key: A): B =
|
||||
|
|
@ -1803,6 +1832,7 @@ proc getOrDefault*[A, B](t: OrderedTableRef[A, B], key: A): B =
|
|||
let a = {'a': 5, 'b': 9}.newOrderedTable
|
||||
doAssert a.getOrDefault('a') == 5
|
||||
doAssert a.getOrDefault('z') == 0
|
||||
|
||||
getOrDefault(t[], key)
|
||||
|
||||
proc getOrDefault*[A, B](t: OrderedTableRef[A, B], key: A, default: B): B =
|
||||
|
|
@ -1820,6 +1850,7 @@ proc getOrDefault*[A, B](t: OrderedTableRef[A, B], key: A, default: B): B =
|
|||
let a = {'a': 5, 'b': 9}.newOrderedTable
|
||||
doAssert a.getOrDefault('a', 99) == 5
|
||||
doAssert a.getOrDefault('z', 99) == 99
|
||||
|
||||
getOrDefault(t[], key, default)
|
||||
|
||||
proc mgetOrPut*[A, B](t: OrderedTableRef[A, B], key: A, val: B): var B =
|
||||
|
|
@ -1839,6 +1870,7 @@ proc mgetOrPut*[A, B](t: OrderedTableRef[A, B], key: A, val: B): var B =
|
|||
doAssert a.mgetOrPut('a', 99) == 5
|
||||
doAssert a.mgetOrPut('z', 99) == 99
|
||||
doAssert a == {'a': 5, 'b': 9, 'z': 99}.newOrderedTable
|
||||
|
||||
result = t[].mgetOrPut(key, val)
|
||||
|
||||
proc len*[A, B](t: OrderedTableRef[A, B]): int {.inline.} =
|
||||
|
|
@ -1846,6 +1878,7 @@ proc len*[A, B](t: OrderedTableRef[A, B]): int {.inline.} =
|
|||
runnableExamples:
|
||||
let a = {'a': 5, 'b': 9}.newOrderedTable
|
||||
doAssert len(a) == 2
|
||||
|
||||
result = t.counter
|
||||
|
||||
proc add*[A, B](t: OrderedTableRef[A, B], key: A, val: B) =
|
||||
|
|
@ -1868,6 +1901,7 @@ proc del*[A, B](t: var OrderedTableRef[A, B], key: A) =
|
|||
doAssert a == {'b': 9, 'c': 13}.newOrderedTable
|
||||
a.del('z')
|
||||
doAssert a == {'b': 9, 'c': 13}.newOrderedTable
|
||||
|
||||
t[].del(key)
|
||||
|
||||
proc clear*[A, B](t: var OrderedTableRef[A, B]) =
|
||||
|
|
@ -1880,6 +1914,7 @@ proc clear*[A, B](t: var OrderedTableRef[A, B]) =
|
|||
doAssert len(a) == 3
|
||||
clear(a)
|
||||
doAssert len(a) == 0
|
||||
|
||||
clear(t[])
|
||||
|
||||
proc sort*[A, B](t: OrderedTableRef[A, B], cmp: proc (x,y: (A, B)): int, order = SortOrder.Ascending) =
|
||||
|
|
@ -1899,6 +1934,7 @@ proc sort*[A, B](t: OrderedTableRef[A, B], cmp: proc (x,y: (A, B)): int, order =
|
|||
doAssert a == {'a': 10, 'b': 20, 'c': 0}.newOrderedTable
|
||||
a.sort(system.cmp, order=SortOrder.Descending)
|
||||
doAssert a == {'c': 0, 'b': 20, 'a': 10}.newOrderedTable
|
||||
|
||||
t[].sort(cmp, order=order)
|
||||
|
||||
proc `$`*[A, B](t: OrderedTableRef[A, B]): string =
|
||||
|
|
@ -1915,6 +1951,7 @@ proc `==`*[A, B](s, t: OrderedTableRef[A, B]): bool =
|
|||
a = {'a': 5, 'b': 9, 'c': 13}.newOrderedTable
|
||||
b = {'b': 9, 'c': 13, 'a': 5}.newOrderedTable
|
||||
doAssert a != b
|
||||
|
||||
if isNil(s): result = isNil(t)
|
||||
elif isNil(t): result = false
|
||||
else: result = s[] == t[]
|
||||
|
|
@ -1964,6 +2001,7 @@ iterator mpairs*[A, B](t: OrderedTableRef[A, B]): (A, var B) =
|
|||
for k, v in a.mpairs:
|
||||
v.add(v[0] + 10)
|
||||
doAssert a == {'o': @[1, 5, 7, 9, 11], 'e': @[2, 4, 6, 8, 12]}.newOrderedTable
|
||||
|
||||
forAllOrderedPairs:
|
||||
yield (t.data[h].key, t.data[h].val)
|
||||
|
||||
|
|
@ -1981,6 +2019,7 @@ iterator keys*[A, B](t: OrderedTableRef[A, B]): A =
|
|||
for k in a.keys:
|
||||
a[k].add(99)
|
||||
doAssert a == {'o': @[1, 5, 7, 9, 99], 'e': @[2, 4, 6, 8, 99]}.newOrderedTable
|
||||
|
||||
forAllOrderedPairs:
|
||||
yield t.data[h].key
|
||||
|
||||
|
|
@ -1998,6 +2037,7 @@ iterator values*[A, B](t: OrderedTableRef[A, B]): B =
|
|||
}.newOrderedTable
|
||||
for v in a.values:
|
||||
doAssert v.len == 4
|
||||
|
||||
forAllOrderedPairs:
|
||||
yield t.data[h].val
|
||||
|
||||
|
|
@ -2016,6 +2056,7 @@ iterator mvalues*[A, B](t: OrderedTableRef[A, B]): var B =
|
|||
for v in a.mvalues:
|
||||
v.add(99)
|
||||
doAssert a == {'o': @[1, 5, 7, 9, 99], 'e': @[2, 4, 6, 8, 99]}.newOrderedTable
|
||||
|
||||
forAllOrderedPairs:
|
||||
yield t.data[h].val
|
||||
|
||||
|
|
@ -2046,7 +2087,7 @@ type
|
|||
|
||||
# ------------------------------ helpers ---------------------------------
|
||||
|
||||
proc rawInsert[A](t: CountTable[A], data: var seq[tuple[key: A, val: int]],
|
||||
proc ctRawInsert[A](t: CountTable[A], data: var seq[tuple[key: A, val: int]],
|
||||
key: A, val: int) =
|
||||
var h: Hash = hash(key) and high(data)
|
||||
while data[h].val != 0: h = nextTry(h, high(data))
|
||||
|
|
@ -2057,10 +2098,12 @@ proc enlarge[A](t: var CountTable[A]) =
|
|||
var n: seq[tuple[key: A, val: int]]
|
||||
newSeq(n, len(t.data) * growthFactor)
|
||||
for i in countup(0, high(t.data)):
|
||||
if t.data[i].val != 0: rawInsert(t, n, t.data[i].key, t.data[i].val)
|
||||
if t.data[i].val != 0: ctRawInsert(t, n, t.data[i].key, t.data[i].val)
|
||||
swap(t.data, n)
|
||||
|
||||
proc rawGet[A](t: CountTable[A], key: A): int =
|
||||
if t.data.len == 0:
|
||||
return -1
|
||||
var h: Hash = hash(key) and high(t.data) # start with real hash value
|
||||
while t.data[h].val != 0:
|
||||
if t.data[h].key == key: return h
|
||||
|
|
@ -2075,7 +2118,7 @@ proc inc*[A](t: var CountTable[A], key: A, val = 1)
|
|||
|
||||
# ----------------------------------------------------------------------
|
||||
|
||||
proc initCountTable*[A](initialSize=64): CountTable[A] =
|
||||
proc initCountTable*[A](initialsize = defaultInitialSize): CountTable[A] =
|
||||
## Creates a new count table that is empty.
|
||||
##
|
||||
## ``initialSize`` must be a power of two (default: 64).
|
||||
|
|
@ -2084,13 +2127,14 @@ proc initCountTable*[A](initialSize=64): CountTable[A] =
|
|||
## `math module<math.html>`_ or the `rightSize proc<#rightSize,Natural>`_
|
||||
## from this module.
|
||||
##
|
||||
## Starting from Nim v0.20, tables are initialized by default and it is
|
||||
## not necessary to call this function explicitly.
|
||||
##
|
||||
## See also:
|
||||
## * `toCountTable proc<#toCountTable,openArray[A]>`_
|
||||
## * `newCountTable proc<#newCountTable,int>`_ for creating a
|
||||
## `CountTableRef`
|
||||
assert isPowerOfTwo(initialSize)
|
||||
result.counter = 0
|
||||
newSeq(result.data, initialSize)
|
||||
initImpl(result, initialSize)
|
||||
|
||||
proc toCountTable*[A](keys: openArray[A]): CountTable[A] =
|
||||
## Creates a new count table with every member of a container ``keys``
|
||||
|
|
@ -2130,9 +2174,7 @@ proc `[]=`*[A](t: var CountTable[A], key: A, val: int) =
|
|||
if h >= 0:
|
||||
t.data[h].val = val
|
||||
else:
|
||||
if mustRehash(len(t.data), t.counter): enlarge(t)
|
||||
rawInsert(t, t.data, key, val)
|
||||
inc(t.counter)
|
||||
insertImpl()
|
||||
|
||||
proc inc*[A](t: var CountTable[A], key: A, val = 1) =
|
||||
## Increments ``t[key]`` by ``val`` (default: 1).
|
||||
|
|
@ -2141,14 +2183,13 @@ proc inc*[A](t: var CountTable[A], key: A, val = 1) =
|
|||
a.inc('a')
|
||||
a.inc('b', 10)
|
||||
doAssert a == toCountTable("aaabbbbbbbbbbb")
|
||||
|
||||
var index = rawGet(t, key)
|
||||
if index >= 0:
|
||||
inc(t.data[index].val, val)
|
||||
if t.data[index].val == 0: dec(t.counter)
|
||||
else:
|
||||
if mustRehash(len(t.data), t.counter): enlarge(t)
|
||||
rawInsert(t, t.data, key, val)
|
||||
inc(t.counter)
|
||||
insertImpl()
|
||||
|
||||
proc smallest*[A](t: CountTable[A]): tuple[key: A, val: int] =
|
||||
## Returns the ``(key, value)`` pair with the smallest ``val``. Efficiency: O(n)
|
||||
|
|
@ -2229,6 +2270,7 @@ proc sort*[A](t: var CountTable[A], order = SortOrder.Descending) =
|
|||
doAssert toSeq(a.values) == @[5, 2, 2, 1, 1]
|
||||
a.sort(SortOrder.Ascending)
|
||||
doAssert toSeq(a.values) == @[1, 1, 2, 2, 5]
|
||||
|
||||
t.data.sort(cmp=ctCmp, order=order)
|
||||
|
||||
proc merge*[A](s: var CountTable[A], t: CountTable[A]) =
|
||||
|
|
@ -2238,6 +2280,7 @@ proc merge*[A](s: var CountTable[A], t: CountTable[A]) =
|
|||
let b = toCountTable("bcc")
|
||||
a.merge(b)
|
||||
doAssert a == toCountTable("aaabbbccc")
|
||||
|
||||
for key, value in t:
|
||||
s.inc(key, value)
|
||||
|
||||
|
|
@ -2248,6 +2291,7 @@ proc merge*[A](s, t: CountTable[A]): CountTable[A] =
|
|||
a = toCountTable("aaabbc")
|
||||
b = toCountTable("bcc")
|
||||
doAssert merge(a, b) == toCountTable("aaabbbccc")
|
||||
|
||||
result = initCountTable[A](nextPowerOfTwo(max(s.len, t.len)))
|
||||
for table in @[s, t]:
|
||||
for key, value in table:
|
||||
|
|
@ -2306,6 +2350,7 @@ iterator mpairs*[A](t: var CountTable[A]): (A, var int) =
|
|||
for k, v in mpairs(a):
|
||||
v = 2
|
||||
doAssert a == toCountTable("aabbccddrr")
|
||||
|
||||
for h in 0..high(t.data):
|
||||
if t.data[h].val != 0: yield (t.data[h].key, t.data[h].val)
|
||||
|
||||
|
|
@ -2320,6 +2365,7 @@ iterator keys*[A](t: CountTable[A]): A =
|
|||
for k in keys(a):
|
||||
a[k] = 2
|
||||
doAssert a == toCountTable("aabbccddrr")
|
||||
|
||||
for h in 0..high(t.data):
|
||||
if t.data[h].val != 0: yield t.data[h].key
|
||||
|
||||
|
|
@ -2334,6 +2380,7 @@ iterator values*[A](t: CountTable[A]): int =
|
|||
let a = toCountTable("abracadabra")
|
||||
for v in values(a):
|
||||
assert v < 10
|
||||
|
||||
for h in 0..high(t.data):
|
||||
if t.data[h].val != 0: yield t.data[h].val
|
||||
|
||||
|
|
@ -2349,6 +2396,7 @@ iterator mvalues*[A](t: var CountTable[A]): var int =
|
|||
for v in mvalues(a):
|
||||
v = 2
|
||||
doAssert a == toCountTable("aabbccddrr")
|
||||
|
||||
for h in 0..high(t.data):
|
||||
if t.data[h].val != 0: yield t.data[h].val
|
||||
|
||||
|
|
@ -2364,7 +2412,7 @@ iterator mvalues*[A](t: var CountTable[A]): var int =
|
|||
|
||||
proc inc*[A](t: CountTableRef[A], key: A, val = 1)
|
||||
|
||||
proc newCountTable*[A](initialSize=64): CountTableRef[A] =
|
||||
proc newCountTable*[A](initialsize = defaultInitialSize): CountTableRef[A] =
|
||||
## Creates a new ref count table that is empty.
|
||||
##
|
||||
## ``initialSize`` must be a power of two (default: 64).
|
||||
|
|
@ -2493,6 +2541,7 @@ proc merge*[A](s, t: CountTableRef[A]) =
|
|||
b = newCountTable("bcc")
|
||||
a.merge(b)
|
||||
doAssert a == newCountTable("aaabbbccc")
|
||||
|
||||
s[].merge(t[])
|
||||
|
||||
proc `$`*[A](t: CountTableRef[A]): string =
|
||||
|
|
@ -2551,6 +2600,7 @@ iterator mpairs*[A](t: CountTableRef[A]): (A, var int) =
|
|||
for k, v in mpairs(a):
|
||||
v = 2
|
||||
doAssert a == newCountTable("aabbccddrr")
|
||||
|
||||
for h in 0..high(t.data):
|
||||
if t.data[h].val != 0: yield (t.data[h].key, t.data[h].val)
|
||||
|
||||
|
|
@ -2565,6 +2615,7 @@ iterator keys*[A](t: CountTableRef[A]): A =
|
|||
for k in keys(a):
|
||||
a[k] = 2
|
||||
doAssert a == newCountTable("aabbccddrr")
|
||||
|
||||
for h in 0..high(t.data):
|
||||
if t.data[h].val != 0: yield t.data[h].key
|
||||
|
||||
|
|
@ -2579,6 +2630,7 @@ iterator values*[A](t: CountTableRef[A]): int =
|
|||
let a = newCountTable("abracadabra")
|
||||
for v in values(a):
|
||||
assert v < 10
|
||||
|
||||
for h in 0..high(t.data):
|
||||
if t.data[h].val != 0: yield t.data[h].val
|
||||
|
||||
|
|
@ -2593,6 +2645,7 @@ iterator mvalues*[A](t: CountTableRef[A]): var int =
|
|||
for v in mvalues(a):
|
||||
v = 2
|
||||
doAssert a == newCountTable("aabbccddrr")
|
||||
|
||||
for h in 0..high(t.data):
|
||||
if t.data[h].val != 0: yield t.data[h].val
|
||||
|
||||
|
|
@ -2813,3 +2866,99 @@ when isMainModule:
|
|||
doAssert "test1" == orf.getOrDefault("test1", "test1")
|
||||
orf["test2"] = "test2"
|
||||
doAssert "test2" == orf.getOrDefault("test2", "test1")
|
||||
|
||||
block tableWithoutInit:
|
||||
var
|
||||
a: Table[string, int]
|
||||
b: Table[string, int]
|
||||
c: Table[string, int]
|
||||
d: Table[string, int]
|
||||
e: Table[string, int]
|
||||
|
||||
a["a"] = 7
|
||||
doAssert a.hasKey("a")
|
||||
doAssert a.len == 1
|
||||
doAssert a["a"] == 7
|
||||
a["a"] = 9
|
||||
doAssert a.len == 1
|
||||
doAssert a["a"] == 9
|
||||
|
||||
doAssert b.hasKeyOrPut("b", 5) == false
|
||||
doAssert b.hasKey("b")
|
||||
doAssert b.hasKeyOrPut("b", 8)
|
||||
doAssert b["b"] == 5
|
||||
|
||||
doAssert c.getOrDefault("a") == 0
|
||||
doAssert c.getOrDefault("a", 3) == 3
|
||||
c["a"] = 6
|
||||
doAssert c.getOrDefault("a", 3) == 6
|
||||
|
||||
doAssert d.mgetOrPut("a", 3) == 3
|
||||
doAssert d.mgetOrPut("a", 6) == 3
|
||||
|
||||
var x = 99
|
||||
doAssert e.take("a", x) == false
|
||||
doAssert x == 99
|
||||
e["a"] = 77
|
||||
doAssert e.take("a", x)
|
||||
doAssert x == 77
|
||||
|
||||
block orderedTableWithoutInit:
|
||||
var
|
||||
a: OrderedTable[string, int]
|
||||
b: OrderedTable[string, int]
|
||||
c: OrderedTable[string, int]
|
||||
d: OrderedTable[string, int]
|
||||
|
||||
a["a"] = 7
|
||||
doAssert a.hasKey("a")
|
||||
doAssert a.len == 1
|
||||
doAssert a["a"] == 7
|
||||
a["a"] = 9
|
||||
doAssert a.len == 1
|
||||
doAssert a["a"] == 9
|
||||
|
||||
doAssert b.hasKeyOrPut("b", 5) == false
|
||||
doAssert b.hasKey("b")
|
||||
doAssert b.hasKeyOrPut("b", 8)
|
||||
doAssert b["b"] == 5
|
||||
|
||||
doAssert c.getOrDefault("a") == 0
|
||||
doAssert c.getOrDefault("a", 3) == 3
|
||||
c["a"] = 6
|
||||
doAssert c.getOrDefault("a", 3) == 6
|
||||
|
||||
doAssert d.mgetOrPut("a", 3) == 3
|
||||
doAssert d.mgetOrPut("a", 6) == 3
|
||||
|
||||
block countTableWithoutInit:
|
||||
var
|
||||
a: CountTable[string]
|
||||
b: CountTable[string]
|
||||
c: CountTable[string]
|
||||
d: CountTable[string]
|
||||
e: CountTable[string]
|
||||
|
||||
a["a"] = 7
|
||||
doAssert a.hasKey("a")
|
||||
doAssert a.len == 1
|
||||
doAssert a["a"] == 7
|
||||
a["a"] = 9
|
||||
doAssert a.len == 1
|
||||
doAssert a["a"] == 9
|
||||
|
||||
doAssert b["b"] == 0
|
||||
b.inc("b")
|
||||
doAssert b["b"] == 1
|
||||
|
||||
doAssert c.getOrDefault("a") == 0
|
||||
doAssert c.getOrDefault("a", 3) == 3
|
||||
c["a"] = 6
|
||||
doAssert c.getOrDefault("a", 3) == 6
|
||||
|
||||
e["f"] = 3
|
||||
merge(d, e)
|
||||
doAssert d.hasKey("f")
|
||||
d.inc("f")
|
||||
merge(d, e)
|
||||
doAssert d["f"] == 7
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue