fix docs + API for fieldPairs, fields (#13189)

This commit is contained in:
Timothee Cour 2020-01-18 04:33:30 -08:00 • committed by Andreas Rumpf
commit bc14453f69

View file

@ -217,45 +217,38 @@ iterator mitems*(a: var string): var char {.inline.} =
iterator fields*[T: tuple|object](x: T): RootObj {. iterator fields*[T: tuple|object](x: T): RootObj {.
magic: "Fields", noSideEffect.} magic: "Fields", noSideEffect.} =
## Iterates over every field of `x`. ## Iterates over every field of `x`.
## ##
## **Warning**: This really transforms the 'for' and unrolls the loop. ## **Warning**: This really transforms the 'for' and unrolls the loop.
## The current implementation also has a bug ## The current implementation also has a bug
## that affects symbol binding in the loop body. ## that affects symbol binding in the loop body.
iterator fields*[S:tuple|object, T:tuple|object](x: S, y: T): tuple[a, b: RootObj] {. runnableExamples:
magic: "Fields", noSideEffect.} var t = (1, "foo")
for v in fields(t): v = default(type(v))
doAssert t == (0, "")
iterator fields*[S:tuple|object, T:tuple|object](x: S, y: T): tuple[key: string, val: RootObj] {.
magic: "Fields", noSideEffect.} =
## Iterates over every field of `x` and `y`. ## Iterates over every field of `x` and `y`.
## ##
## **Warning**: This really transforms the 'for' and unrolls the loop. ## **Warning**: This really transforms the 'for' and unrolls the loop.
## The current implementation also has a bug that affects symbol binding ## The current implementation also has a bug that affects symbol binding
## in the loop body. ## in the loop body.
iterator fieldPairs*[T: tuple|object](x: T): RootObj {. runnableExamples:
magic: "FieldPairs", noSideEffect.} var t1 = (1, "foo")
var t2 = default(type(t1))
for v1, v2 in fields(t1, t2): v2 = v1
doAssert t1 == t2
iterator fieldPairs*[T: tuple|object](x: T): tuple[key: string, val: RootObj] {.
magic: "FieldPairs", noSideEffect.} =
## Iterates over every field of `x` returning their name and value. ## Iterates over every field of `x` returning their name and value.
## ##
## When you iterate over objects with different field types you have to use ## When you iterate over objects with different field types you have to use
## the compile time ``when`` instead of a runtime ``if`` to select the code ## the compile time ``when`` instead of a runtime ``if`` to select the code
## you want to run for each type. To perform the comparison use the `is ## you want to run for each type. To perform the comparison use the `is
## operator <manual.html#generics-is-operator>`_. Example: ## operator <manual.html#generics-is-operator>`_.
##
## .. code-block:: Nim
## type
## Custom = object
## foo: string
## bar: bool
##
## proc `$`(x: Custom): string =
## result = "Custom:"
## for name, value in x.fieldPairs:
## when value is bool:
## result.add("\n\t" & name & " is " & $value)
## else:
## if value.isNil:
## result.add("\n\t" & name & " (nil)")
## else:
## result.add("\n\t" & name & " '" & value & "'")
##
## Another way to do the same without ``when`` is to leave the task of ## Another way to do the same without ``when`` is to leave the task of
## picking the appropriate code to a secondary proc which you overload for ## picking the appropriate code to a secondary proc which you overload for
## each field type and pass the `value` to. ## each field type and pass the `value` to.
@ -263,12 +256,33 @@ iterator fieldPairs*[T: tuple|object](x: T): RootObj {.
## **Warning**: This really transforms the 'for' and unrolls the loop. The ## **Warning**: This really transforms the 'for' and unrolls the loop. The
## current implementation also has a bug that affects symbol binding in the ## current implementation also has a bug that affects symbol binding in the
## loop body. ## loop body.
runnableExamples:
type
Custom = object
foo: string
bar: bool
proc `$`(x: Custom): string =
result = "Custom:"
for name, value in x.fieldPairs:
when value is bool:
result.add("\n\t" & name & " is " & $value)
else:
result.add("\n\t" & name & " '" & value & "'")
iterator fieldPairs*[S: tuple|object, T: tuple|object](x: S, y: T): tuple[ iterator fieldPairs*[S: tuple|object, T: tuple|object](x: S, y: T): tuple[
a, b: RootObj] {. key: string, a, b: RootObj] {.
magic: "FieldPairs", noSideEffect.} magic: "FieldPairs", noSideEffect.} =
## Iterates over every field of `x` and `y`. ## Iterates over every field of `x` and `y`.
## ##
## **Warning**: This really transforms the 'for' and unrolls the loop. ## **Warning**: This really transforms the 'for' and unrolls the loop.
## The current implementation also has a bug that affects symbol binding ## The current implementation also has a bug that affects symbol binding
## in the loop body. ## in the loop body.
runnableExamples:
type Foo = object
x1: int
x2: string
var a1 = Foo(x1: 12, x2: "abc")
var a2: Foo
for name, v1, v2 in fieldPairs(a1, a2):
when name == "x2": v2 = v1
doAssert a2 == Foo(x1: 0, x2: "abc")