Skip to content

Commit e2bc9a4

Browse files
committed
add docstrings
1 parent 2bb69d8 commit e2bc9a4

File tree

1 file changed

+199
-16
lines changed

1 file changed

+199
-16
lines changed

src/swiss_dict.jl

Lines changed: 199 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,31 @@
1-
const SWISS_DICT_LOAD_FACTOR = 0.75
1+
const SWISS_DICT_LOAD_FACTOR = 0.97
22
const _u8x16 = NTuple{16, VecElement{UInt8}}
33

4+
"""
5+
SwissDict([itr])
6+
7+
`SwissDict{K,V}()` constructs a hash table with keys of type `K` and values of type `V`.
8+
Keys are compared with [`isequal`](@ref) and hashed with [`hash`](@ref).
9+
Given a single iterable argument, constructs a [`SwissDict`](@ref) whose key-value pairs
10+
are taken from 2-tuples `(key,value)` generated by the argument.
11+
12+
# Examples
13+
```jldoctest
14+
julia> SwissDict([("A", 1), ("B", 2)])
15+
SwissDict{String,Int64} with 2 entries:
16+
"B" => 2
17+
"A" => 1
18+
```
19+
20+
Alternatively, a sequence of pair arguments may be passed.
21+
22+
```jldoctest
23+
julia> SwissDict("A"=>1, "B"=>2)
24+
SwissDict{String,Int64} with 2 entries:
25+
"B" => 2
26+
"A" => 1
27+
```
28+
"""
429
mutable struct SwissDict{K,V} <: AbstractDict{K,V}
530
slots::Vector{_u8x16}
631
keys::Vector{K}
@@ -57,7 +82,7 @@ function SwissDict(kv)
5782
end
5883
end
5984

60-
##SIMD utilities
85+
# SIMD utilities
6186
@inline _expand16(u::UInt8) = ntuple(i->VecElement(u), Val(16))
6287
_blsr(i::UInt32)= i & (i-Int32(1))
6388

@@ -215,6 +240,7 @@ function _iterslots(h::SwissDict, start::Int)
215240
sl = ((~sl & 0xffff)>>off) << off
216241
return _iterslots(h, (i0, sl))
217242
end
243+
218244
function _iterslots(h::SwissDict, state)
219245
i, sl = state
220246
while iszero(sl)
@@ -248,12 +274,6 @@ function maybe_rehash_shrink!(h::SwissDict)
248274
end
249275
end
250276

251-
# function _dictsizehint(sz)
252-
# (sz <= 16) && return 16
253-
# nsz = _tablesz(sz)
254-
# return (sz > SWISS_DICT_LOAD_FACTOR*nsz) ? (nsz<<1) : nsz
255-
# end
256-
257277
function sizehint!(d::SwissDict, newsz)
258278
newsz = _tablesz(newsz*2) # *2 for keys and values in same array
259279
oldsz = length(d.keys)
@@ -328,6 +348,24 @@ end
328348
isempty(t::SwissDict) = (t.count == 0)
329349
length(t::SwissDict) = t.count
330350

351+
"""
352+
empty!(collection) -> collection
353+
354+
Remove all elements from a `collection`.
355+
356+
# Examples
357+
```jldoctest
358+
julia> A = SwissDict("a" => 1, "b" => 2)
359+
SwissDict{String,Int64} with 2 entries:
360+
"b" => 2
361+
"a" => 1
362+
363+
julia> empty!(A);
364+
365+
julia> A
366+
SwissDict{String,Int64} with 0 entries
367+
```
368+
"""
331369
function empty!(h::SwissDict{K,V}) where {K, V}
332370
fill!(h.slots, _expand16(0x00))
333371
sz = length(h.keys)
@@ -344,9 +382,6 @@ end
344382

345383
function setindex!(h::SwissDict{K,V}, v0, key0) where {K, V}
346384
key = convert(K, key0)
347-
if !isequal(key, key0)
348-
throw(ArgumentError("$(limitrepr(key0)) is not a valid key for type $K"))
349-
end
350385
_setindex!(h, v0, key)
351386
end
352387

@@ -359,23 +394,61 @@ function _setindex!(h::SwissDict{K,V}, v0, key::K) where {K, V}
359394
@inbounds h.keys[index] = key
360395
@inbounds h.vals[index] = v
361396
else
362-
@inbounds _setindex!(h, v, key, -index, tag)
397+
_setindex!(h, v, key, -index, tag)
363398
end
364399

365400
return h
366401
end
367402

403+
"""
404+
get!(collection, key, default)
405+
406+
Return the value stored for the given key, or if no mapping for the key is present, store
407+
`key => default`, and return `default`.
408+
409+
# Examples
410+
```jldoctest
411+
julia> d = SwissDict("a"=>1, "b"=>2, "c"=>3);
412+
413+
julia> get!(d, "a", 5)
414+
1
415+
416+
julia> get!(d, "d", 4)
417+
4
418+
419+
julia> d
420+
SwissDict{String,Int64} with 4 entries:
421+
"c" => 3
422+
"b" => 2
423+
"a" => 1
424+
"d" => 4
425+
```
426+
"""
368427
get!(h::SwissDict{K,V}, key0, default) where {K,V} = get!(()->default, h, key0)
369428

429+
"""
430+
get!(f::Function, collection, key)
431+
432+
Return the value stored for the given key, or if no mapping for the key is present, store
433+
`key => f()`, and return `f()`.
434+
435+
This is intended to be called using `do` block syntax:
436+
```julia
437+
get!(dict, key) do
438+
# default value calculated here
439+
time()
440+
end
441+
```
442+
"""
370443
function get!(default::Callable, h::SwissDict{K,V}, key0) where {K, V}
371444
key = convert(K, key0)
372-
return get!(default, h, key)
445+
return _get!(default, h, key)
373446
end
374447

375-
function get!(default::Callable, h::SwissDict{K,V}, key::K) where {K, V}
448+
function _get!(default::Callable, h::SwissDict{K,V}, key::K) where {K, V}
376449
index, tag = ht_keyindex2!(h, key)
377450

378-
index > 0 && return h.vals[index]
451+
index > 0 && return @inbounds h.vals[index]
379452

380453
age0 = h.age
381454
v = convert(V, default())
@@ -387,7 +460,7 @@ function get!(default::Callable, h::SwissDict{K,V}, key::K) where {K, V}
387460
@inbounds h.keys[index] = key
388461
@inbounds h.vals[index] = v
389462
else
390-
@inbounds _setindex!(h, v, key, -index, tag)
463+
_setindex!(h, v, key, -index, tag)
391464
end
392465
return v
393466
end
@@ -397,25 +470,118 @@ function getindex(h::SwissDict{K,V}, key) where {K, V}
397470
@inbounds return (index < 0) ? throw(KeyError(key)) : h.vals[index]::V
398471
end
399472

473+
"""
474+
get(collection, key, default)
475+
476+
Return the value stored for the given key, or the given default value if no mapping for the
477+
key is present.
478+
479+
# Examples
480+
```jldoctest
481+
julia> d = SwissDict("a"=>1, "b"=>2);
482+
483+
julia> get(d, "a", 3)
484+
1
485+
486+
julia> get(d, "c", 3)
487+
3
488+
```
489+
"""
400490
function get(h::SwissDict{K,V}, key, default) where {K, V}
401491
index = ht_keyindex(h, key)
402492
@inbounds return (index < 0) ? default : h.vals[index]::V
403493
end
404494

495+
"""
496+
get(f::Function, collection, key)
497+
498+
Return the value stored for the given key, or if no mapping for the key is present, return
499+
`f()`. Use [`get!`](@ref) to also store the default value in the dictionary.
500+
501+
This is intended to be called using `do` block syntax
502+
503+
```julia
504+
get(dict, key) do
505+
# default value calculated here
506+
time()
507+
end
508+
```
509+
"""
405510
function get(default::Callable, h::SwissDict{K,V}, key) where {K, V}
406511
index = ht_keyindex(h, key)
407512
@inbounds return (index < 0) ? default() : h.vals[index]::V
408513
end
409514

515+
"""
516+
haskey(collection, key) -> Bool
517+
518+
Determine whether a collection has a mapping for a given `key`.
519+
520+
# Examples
521+
```jldoctest
522+
julia> D = SwissDict('a'=>2, 'b'=>3)
523+
SwissDict{Char,Int64} with 2 entries:
524+
'a' => 2
525+
'b' => 3
526+
527+
julia> haskey(D, 'a')
528+
true
529+
530+
julia> haskey(D, 'c')
531+
false
532+
```
533+
"""
410534
haskey(h::SwissDict, key) = (ht_keyindex(h, key) > 0)
411535
in(key, v::KeySet{<:Any, <:SwissDict}) = (ht_keyindex(v.dict, key) > 0)
412536

537+
"""
538+
getkey(collection, key, default)
539+
540+
Return the key matching argument `key` if one exists in `collection`, otherwise return `default`.
541+
542+
# Examples
543+
```jldoctest
544+
julia> D = SwissDict('a'=>2, 'b'=>3)
545+
SwissDict{Char,Int64} with 2 entries:
546+
'a' => 2
547+
'b' => 3
548+
549+
julia> getkey(D, 'a', 1)
550+
'a': ASCII/Unicode U+0061 (category Ll: Letter, lowercase)
413551
552+
julia> getkey(D, 'd', 'a')
553+
'a': ASCII/Unicode U+0061 (category Ll: Letter, lowercase)
554+
```
555+
"""
414556
function getkey(h::SwissDict{K,V}, key, default) where {K, V}
415557
index = ht_keyindex(h, key)
416558
@inbounds return (index<0) ? default : h.keys[index]::K
417559
end
418560

561+
"""
562+
pop!(collection, key[, default])
563+
564+
Delete and return the mapping for `key` if it exists in `collection`, otherwise return
565+
`default`, or throw an error if `default` is not specified.
566+
567+
# Examples
568+
```jldoctest
569+
julia> d = SwissDict("a"=>1, "b"=>2, "c"=>3);
570+
571+
julia> pop!(d, "a")
572+
1
573+
574+
julia> pop!(d, "d")
575+
ERROR: KeyError: key "d" not found
576+
Stacktrace:
577+
[...]
578+
579+
julia> pop!(d, "e", 4)
580+
4
581+
```
582+
"""
583+
pop!(collection, key, default)
584+
419585
function _pop!(h::SwissDict, index)
420586
@inbounds val = h.vals[index]
421587
_delete!(h, index)
@@ -445,6 +611,23 @@ function pop!(h::SwissDict)
445611
return key => val
446612
end
447613

614+
"""
615+
delete!(collection, key)
616+
617+
Delete the mapping for the given key in a collection, and return the collection.
618+
619+
# Examples
620+
```jldoctest
621+
julia> d = SwissDict("a"=>1, "b"=>2)
622+
SwissDict{String,Int64} with 2 entries:
623+
"b" => 2
624+
"a" => 1
625+
626+
julia> delete!(d, "b")
627+
SwissDict{String,Int64} with 1 entry:
628+
"a" => 1
629+
```
630+
"""
448631
function delete!(h::SwissDict, key)
449632
index = ht_keyindex(h, key)
450633
if index > 0

0 commit comments

Comments
 (0)