Nim - 如何在编译时访问类型为 Option[mytype] 的字段的 mytype?
Nim - How to access mytype of a field that has the type Option[mytype] at compile time?
嘿嘿,
在通过一些泛型编写代码时,我偶然发现了我的一个泛型函数的问题。
我有 2 种类型,比如这个
import std/options
import norm
type
A = ref object of Model
name: string
B = ref object of Model
name: string
myA: Option[A]
norm,nim 中用于 sqlite 的 ORM,我可以通过具有类型在编译时获取模型所属的 sql-表名继承自 Model 并在其上调用 table()
。
出于各种原因,我希望能够找出给定模型链接到的所有表的名称。在这种情况下,B
链接到 A
类型,但我需要在编译时调用 A.table()
来获取该表名(如果 {.tableName.}
编译指示可以是任何内容正在使用中)。
但是,我似乎找不到访问我的类型的方法,因为我无法在编译时调用 options
模块的典型 get()
方法。我的出路在哪里?
感谢 nim-discord 服务器上的热心帮助(大声喊叫 leorize),我才得以解决这个问题。事实上,我提出这个问题只是为了让我自己 google 更容易回答。
有多种方法可以解决这个问题:
- 尝试直接访问类型
Option
的泛型参数称为T
。其中 T
是您要查找的类型。
proc getRelatedFieldName[M: Model, O:Model](targetType: typedesc[O], sourceType: typedesc[M]): Option[string] =
let source = sourceType()
for sourceFieldName, sourceFieldValue in source[].fieldPairs:
when sourceFieldValue is Option:
when sourceFieldValue.get() is Model:
when O.table() == sourceFieldValue.T.table():
return some(sourceFieldName)
return none(string)
echo A.getRelatedFieldName(B) # returns "some('myA')"
如果您使用的不是 typedesc 而是实际类型,您可能需要考虑使用 typeof(sourceFieldValue).T.table()
。
- 使用
typetrait
的genericParams
函数
您可以使用 [typetraits][1]
库及其 genericParams 函数。
genericParams(B).get(0)
使用 genericParams 作为工具,您可以做一些有趣的事情,比如在编译时迭代一个类型的所有字段(不是实例!),检查给定字段是否是模型的选项并比较表名
proc getRelatedFieldName[M: Model, O:Model](targetType: typedesc[O], sourceType: typedesc[M]): Option[string] =
let source = sourceType()
for sourceFieldName, sourceFieldValue in source[].fieldPairs:
when sourceFieldValue is Option:
when sourceFieldValue.get() is Model:
when O.table() == genericParams(sourceFieldValue.type()).get(0).table():
return some(sourceFieldName)
return none(string)
echo A.getRelatedFieldName(B) # returns "some('myA')"
嘿嘿,
在通过一些泛型编写代码时,我偶然发现了我的一个泛型函数的问题。 我有 2 种类型,比如这个
import std/options
import norm
type
A = ref object of Model
name: string
B = ref object of Model
name: string
myA: Option[A]
norm,nim 中用于 sqlite 的 ORM,我可以通过具有类型在编译时获取模型所属的 sql-表名继承自 Model 并在其上调用 table()
。
出于各种原因,我希望能够找出给定模型链接到的所有表的名称。在这种情况下,B
链接到 A
类型,但我需要在编译时调用 A.table()
来获取该表名(如果 {.tableName.}
编译指示可以是任何内容正在使用中)。
但是,我似乎找不到访问我的类型的方法,因为我无法在编译时调用 options
模块的典型 get()
方法。我的出路在哪里?
感谢 nim-discord 服务器上的热心帮助(大声喊叫 leorize),我才得以解决这个问题。事实上,我提出这个问题只是为了让我自己 google 更容易回答。
有多种方法可以解决这个问题:
- 尝试直接访问类型
Option
的泛型参数称为T
。其中 T
是您要查找的类型。
proc getRelatedFieldName[M: Model, O:Model](targetType: typedesc[O], sourceType: typedesc[M]): Option[string] =
let source = sourceType()
for sourceFieldName, sourceFieldValue in source[].fieldPairs:
when sourceFieldValue is Option:
when sourceFieldValue.get() is Model:
when O.table() == sourceFieldValue.T.table():
return some(sourceFieldName)
return none(string)
echo A.getRelatedFieldName(B) # returns "some('myA')"
如果您使用的不是 typedesc 而是实际类型,您可能需要考虑使用 typeof(sourceFieldValue).T.table()
。
- 使用
typetrait
的genericParams
函数
您可以使用 [typetraits][1]
库及其 genericParams 函数。
genericParams(B).get(0)
使用 genericParams 作为工具,您可以做一些有趣的事情,比如在编译时迭代一个类型的所有字段(不是实例!),检查给定字段是否是模型的选项并比较表名
proc getRelatedFieldName[M: Model, O:Model](targetType: typedesc[O], sourceType: typedesc[M]): Option[string] =
let source = sourceType()
for sourceFieldName, sourceFieldValue in source[].fieldPairs:
when sourceFieldValue is Option:
when sourceFieldValue.get() is Model:
when O.table() == genericParams(sourceFieldValue.type()).get(0).table():
return some(sourceFieldName)
return none(string)
echo A.getRelatedFieldName(B) # returns "some('myA')"