Nim
Nim copied to clipboard
Template can not be used to evaluate to iterator expression
What happened?
I'm trying to have a template evaluate to a specific iterator under varying circumstances.
While the direct expression that I want (e.g. A().fieldPairs
) works when entered, it can not work when you put the very same code into a template.
Minimal example:
template fieldPairsR(t: typedesc[T]) =
T().fieldPairs
type A = object
field1: string
field2: string
# This compiles
for name, value in A().fieldPairs:
echo name
# This does not compile, even though fieldPairsR(A) should be evaluating to "A().fieldPairs"
for name, value in fieldPairsR(A):
echo name
Nim Version
Nim Compiler Version 1.7.1 [Linux: amd64] Compiled at 2022-08-04 Copyright (c) 2006-2022 by Andreas Rumpf
active boot switches: -d:release
Current Standard Output Logs
Error: attempting to call routine: 'fieldPairs'
found iterators.fieldPairs(x: S: tuple or object, y: T: tuple or object) [iterator declared in /usr/lib/nim/system/iterators.nim(323, 10)]
found iterators.fieldPairs(x: T: tuple or object) [iterator declared in /usr/lib/nim/system/iterators.nim(295, 10)]
Expected Standard Output Logs
field1
field2
Possible Solution
I have no idea what's broken here, this is outside of my level of expertise.
Additional Information
According to leorize this (or similar issues?) appear to be known bugs. I went over issues with the keywords "template" and "iterator" but couldn't find any that were exact matches. If there are any and I missed them, please say so.
Workaround
template fieldPairsR[T](t: typedesc[T]): untyped =
T().fieldPairs
type A = object
field1: string
field2: string
# This compiles
for name, value in A().fieldPairs:
echo name
for name, value in fieldPairsR(A):
echo name
Wait, given that that works, does that even make this a bug still?
I'm not experienced in templates/macros either.
According to https://scripter.co/notes/nim/#return-type-of-templates
Thanks to @mratsim from GitHub for this reply to my question regarding untyped return type for templates:
untyped is useful to make sure the replacement is done before any semantic checking/type resolution.
If you are getting confused about whether or not to set a template’s return type or what to set it to, just set it to untyped.
If in doubt, set a template’s return type as untyped.
Wait, given that that works, does that even make this a bug still?
It probably works as expected, closing.