Hi!
I'm trying to use [] proc from typeinfo module to access object field byt name, but even the most basic code doesn't compile:
import typeinfo
type
Foo = object
field: int
let foo = Foo(field: 123)
echo foo.field # works
echo foo["field"] # fails
Is it a bug to report or am I doing it wrong?
The following code works:
import typeinfo
type
Foo = object
field: int
var foo = Foo(field: 123)
echo foo.field
let x = foo.toAny
echo x["field"].getInt
You can use fieldPairs to get field value by name.
type
Foo = object
field: int
proc `[]`(x: Foo, s: string, T: type): T =
for n, v in x.fieldPairs:
if n == s:
result = v
break
var foo = Foo(field: 123)
echo foo.field
echo foo["field", int]
That won't work when Foo has multiple fields of different types, since v might not be the correct type. Something like this works however:
type
Foo = object
field: int
str: string
proc `[]`(x: Foo, s: string, T: type): T =
for n, v in x.fieldPairs:
if n == s:
when v is T:
return v
else:
raiseAssert "Field has wrong type"
raiseAssert "Field does not exist"
var foo = Foo(field: 123, str: "abc")
echo foo["field", int]
echo foo["str", string]
I ended up writing these templates to convert bracket notation to dot notation:
import macros
macro `[]`*(obj: object, fieldName: string): untyped =
## Access object field value by name: ``obj["field"]`` translates to ``obj.field``.
runnableExamples:
type
Example = object
field: int
let example = Example(field: 123)
doAssert example["field"] == example.field
newDotExpr(obj, newIdentNode(fieldName.strVal))
macro `[]=`*(obj: var object, fieldName: string, value: untyped): untyped =
## Set object field value by name: ``obj["field"] = value`` translates to ``obj.field = value``.
runnableExamples:
type
Example = object
field: int
var example = Example()
example["field"] = 321
doAssert example["field"] == 321
newAssignment(newDotExpr(obj, newIdentNode(fieldName.strVal)), value)