如何在 Nim 中检查未命名的元组?
How to check for unnamed tuple in Nim?
如果就地定义了元组,则下面的宏有效,但如果它是通过类型名称定义的,则无效。
import macros
macro is_unnamed_tuple[T](TT: type[T]): bool =
# nnkTupleTy - named
let r = new_lit(TT.getTypeInst[1].kind == nnkTupleConstr)
quote do:
`r`
type NamedT = tuple[a: string]
type UnnamedT = (string,)
echo is_unnamed_tuple tuple[a: string] # => false
echo is_unnamed_tuple NamedT # => false
echo is_unnamed_tuple (string,) # => true
echo is_unnamed_tuple UnnamedT # => false <- Error
P.S.
也许有更简单的方法来检查它,比如 T is named tuple
或类似的东西?
此外,是否可以进行类似的检查对象是否为 variant
?
Here都是宏。
import std/macros
macro is_unnamed_tuple(T: typedesc): bool =
# nnkTupleTy - named
if T.kind != nnkTupleConstr:
if T.kind == nnkSym:
result = newLit( T.getImpl[^1].kind == nnkTupleConstr)
else:
result = newLit(false)
else:
result = newLit(true)
macro isVariant(T: typedesc): bool =
result = newLit(false)
let impl = T.getImpl
if impl.kind != nnkNilLit:
let objImpl =
if impl[^1].kind == nnkRefTy:
impl[^1][0]
else:
impl[^1]
if objImpl.kind == nnkObjectTy:
for x in objImpl[^1]:
if x.kind == nnkRecCase:
result = newLit(true)
break
type
NamedT = tuple[a: string]
UnnamedT = (string,)
VarObj = object
a: int
case t: bool
of true: discard
of false: discard
assert is_unnamed_tuple(tuple[a: string]) == false
assert is_unnamed_tuple(NamedT) == false
assert is_unnamed_tuple((string,)) == true
assert is_unnamed_tuple(UnnamedT) == true
assert string.isVariant == false
assert VarObj.isVariant == true
assert int.isVariant == false
如果就地定义了元组,则下面的宏有效,但如果它是通过类型名称定义的,则无效。
import macros
macro is_unnamed_tuple[T](TT: type[T]): bool =
# nnkTupleTy - named
let r = new_lit(TT.getTypeInst[1].kind == nnkTupleConstr)
quote do:
`r`
type NamedT = tuple[a: string]
type UnnamedT = (string,)
echo is_unnamed_tuple tuple[a: string] # => false
echo is_unnamed_tuple NamedT # => false
echo is_unnamed_tuple (string,) # => true
echo is_unnamed_tuple UnnamedT # => false <- Error
P.S.
也许有更简单的方法来检查它,比如 T is named tuple
或类似的东西?
此外,是否可以进行类似的检查对象是否为 variant
?
Here都是宏。
import std/macros
macro is_unnamed_tuple(T: typedesc): bool =
# nnkTupleTy - named
if T.kind != nnkTupleConstr:
if T.kind == nnkSym:
result = newLit( T.getImpl[^1].kind == nnkTupleConstr)
else:
result = newLit(false)
else:
result = newLit(true)
macro isVariant(T: typedesc): bool =
result = newLit(false)
let impl = T.getImpl
if impl.kind != nnkNilLit:
let objImpl =
if impl[^1].kind == nnkRefTy:
impl[^1][0]
else:
impl[^1]
if objImpl.kind == nnkObjectTy:
for x in objImpl[^1]:
if x.kind == nnkRecCase:
result = newLit(true)
break
type
NamedT = tuple[a: string]
UnnamedT = (string,)
VarObj = object
a: int
case t: bool
of true: discard
of false: discard
assert is_unnamed_tuple(tuple[a: string]) == false
assert is_unnamed_tuple(NamedT) == false
assert is_unnamed_tuple((string,)) == true
assert is_unnamed_tuple(UnnamedT) == true
assert string.isVariant == false
assert VarObj.isVariant == true
assert int.isVariant == false