add enumutils.items for sparse enums, typetraits.SomeSparseEnum (#17080)

* add enumutils.items for enum with holes
* changelog
* ref in lib.rst
* use `type SomeSparseEnum* = (not Ordinal) and enum` instead of concept
* address comment: rename back to enum with holes
This commit is contained in:
Timothee Cour
2021-02-23 11:25:35 -08:00
committed by GitHub
parent 74a8f23801
commit c274e67198
6 changed files with 58 additions and 6 deletions

View File

@@ -41,8 +41,10 @@
- Added `randState` template that exposes the default random number generator.
Useful for library authors.
- Added std/enumutils module containing `genEnumCaseStmt` macro that generates
case statement to parse string to enum.
- Added `std/enumutils` module. Added `genEnumCaseStmt` macro that generates case statement to parse string to enum.
Added `items` for enums with holes.
- Added `typetraits.SomeEnumWithHoles` for enums with holes.
- Removed deprecated `iup` module from stdlib, it has already moved to
[nimble](https://github.com/nim-lang/iup).

View File

@@ -85,6 +85,9 @@ Algorithms
* `algorithm <algorithm.html>`_
This module implements some common generic algorithms like sort or binary search.
* `std/enumutils <enumutils.html>`_
This module adds functionality for the built-in ``enum`` type.
* `sequtils <sequtils.html>`_
This module implements operations for the built-in ``seq`` type
which were inspired by functional programming languages.

View File

@@ -15,6 +15,17 @@
import std/private/since
export system.`$` # for backward compatibility
type SomeEnumWithHoles* = (not Ordinal) and enum ## Enum with holes.
runnableExamples:
type A = enum a0 = 2, a1 = 4, a2
type B = enum b0 = 2, b1, b2
assert A is SomeEnumWithHoles
assert B isnot SomeEnumWithHoles
assert int isnot SomeEnumWithHoles
type C[T] = enum h0 = 2, h1 = 4
assert C[float] is SomeEnumWithHoles
proc name*(t: typedesc): string {.magic: "TypeTrait".} =
## Returns the name of the given type.
##

View File

@@ -7,7 +7,9 @@
# distribution, for details about the copyright.
#
import macros
import std/macros
# xxx `genEnumCaseStmt` needs tests and runnableExamples
macro genEnumCaseStmt*(typ: typedesc, argSym: typed, default: typed,
userMin, userMax: static[int], normalizer: static[proc(s :string): string]): untyped =
@@ -61,4 +63,17 @@ macro genEnumCaseStmt*(typ: typedesc, argSym: typed, default: typed,
result.add nnkElse.newTree(raiseStmt)
else:
expectKind(default, nnkSym)
result.add nnkElse.newTree(default)
result.add nnkElse.newTree(default)
macro enumWithHolesFullRange(a: typed): untyped =
newNimNode(nnkCurly).add(a.getType[1][1..^1])
iterator items*[T: enum and not Ordinal](E: typedesc[T]): T =
## Iterates over an enum with holes.
runnableExamples:
type A = enum a0 = 2, a1 = 4, a2
type B[T] = enum b0 = 2, b1 = 4
from std/sequtils import toSeq
assert A.toSeq == [a0, a1, a2]
assert B[float].toSeq == [B[float].b0, B[float].b1]
for a in enumWithHolesFullRange(E): yield a

View File

@@ -82,8 +82,13 @@ iterator mitems*(a: var cstring): var char {.inline.} =
yield a[i]
inc(i)
iterator items*[T: enum](E: typedesc[T]): T =
## Iterates over the values of the enum ``E``.
iterator items*[T: enum and Ordinal](E: typedesc[T]): T =
## Iterates over the values of `E`.
## See also `enumutils.items` for enums with holes.
runnableExamples:
type Goo = enum g0 = 2, g1, g2
from std/sequtils import toSeq
assert Goo.toSeq == [g0, g1, g2]
for v in low(E) .. high(E):
yield v

View File

@@ -0,0 +1,16 @@
discard """
targets: "c js"
"""
import std/enumutils
from std/sequtils import toSeq
template main =
block: # items
type A = enum a0 = 2, a1 = 4, a2
type B[T] = enum b0 = 2, b1 = 4
doAssert A.toSeq == [a0, a1, a2]
doAssert B[float].toSeq == [B[float].b0, B[float].b1]
static: main()
main()