是否可以自动编写远程功能的实现?
如果是手工编写的,它看起来就像下面的代码。功能声明和实现都很重要。
proc rcall*[A, B, R](fn: string, a: A, b: B, _: type[R]): R =
echo (fn, a, b)
proc multiply(a, b: int): int
proc multiply(a, b: int): int =
rcall("multiply", a, b, int)我想把它自动化,并把它写成
proc rcall*[A, B, R](fn: string, a: A, b: B, _: type[R]): R =
echo (fn, a, b)
proc multiply(a, b: int): int
remotefn multiplyremotefn宏应该查看函数定义并将其实现生成为rcall("multiply", a, b, int),这是可能的吗?
发布于 2021-04-18 15:42:07
是否可以自动编写实现.
是的,可以使用带有typed参数的nim宏(然后是getTypeImpl)实现几乎任何东西的自动实现。
import std/macros
macro dumpImpl(arg: typed): untyped =
echo arg.getTypeImpl().treeRepr()
proc rcall*[A, B, R](fn: string, a: A, b: B, _: type[R]): R =
echo (fn, a, b)
proc multiply(a, b: int): int
proc multiply(a, b: int): int =
rcall("multiply", a, b, int)
dumpImpl multiply显示multiply类型(函数签名)具有以下结构:
ProcTy
FormalParams
Sym "int"
IdentDefs
Sym "a"
Sym "int"
Empty
IdentDefs
Sym "b"
Sym "int"
Empty
Empty尽管重要的是要记住,仅根据名称(因为,嗯,有许多实现)无法轻松地解析重载的过程。最明显的选择是仍然使用typed参数,但传递一些参数来消除函数调用的歧义。
import std/macros
macro dumpImpl(arg: typed): untyped =
echo arg.treeRepr()
proc overload(a: string) = discard
proc overload(a: int) = discard
dumpImpl overload
# ClosedSymChoice - lists all possible overloads with their respective symbols
# Sym "overload"
# Sym "overload"
dumpImpl overload("123")
#Call
# Sym "overload"
# StrLit "123"
dumpImpl overload(123)
#Call
# Sym "overload"
# IntLit 123作为一个小(个人)方面的注意--当你谈论尼姆宏时,问题主要不应该是“如果这是可能的话?”而是“最理想的方法是什么?”它可能需要一些宏技巧的知识,但几乎可以实现任何东西。
EDIT1 (添加实现代码示例,在注释中回答问题):
import std/[macros]
proc rcall*[A, B, R](fn: string, a: A, b: B, _: type[R]): R =
echo (fn, a, b)
macro remotefn(fn: typed) =
let fname = fn.str_val()
# `quote do` generates hygienic identifiers - i.e. all new
# variables/functions introduced by it are unique and not visible in
# global. To fix this you need to explicitly create identifier for your
# procedure using `ident`
let
multId = ident("multiply") # < Function name identifier
# Same goes for variables - nim does have a name-based overloading, so
# you need to make sure function arguments use the same identifiers as
# the original one
aId = ident("a")
bId = ident("b")
result = quote do:
proc `multId`(`aId`, `bId`: int): int =
rcall(`fname`, 1, 1, int)
echo result.toStrLit()
proc multiply(a, b: int): int
remotefn multiplyhttps://stackoverflow.com/questions/67150226
复制相似问题