首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >宏通过其定义生成函数实现?

宏通过其定义生成函数实现?
EN

Stack Overflow用户
提问于 2021-04-18 15:24:14
回答 1查看 105关注 0票数 0

是否可以自动编写远程功能的实现?

如果是手工编写的,它看起来就像下面的代码。功能声明和实现都很重要。

代码语言:javascript
复制
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)

我想把它自动化,并把它写成

代码语言:javascript
复制
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 multiply

remotefn宏应该查看函数定义并将其实现生成为rcall("multiply", a, b, int),这是可能的吗?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-04-18 15:42:07

是否可以自动编写实现.

是的,可以使用带有typed参数的nim宏(然后是getTypeImpl)实现几乎任何东西的自动实现。

代码语言:javascript
复制
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类型(函数签名)具有以下结构:

代码语言:javascript
复制
ProcTy
  FormalParams
    Sym "int"
    IdentDefs
      Sym "a"
      Sym "int"
      Empty
    IdentDefs
      Sym "b"
      Sym "int"
      Empty
  Empty

尽管重要的是要记住,仅根据名称(因为,嗯,有许多实现)无法轻松地解析重载的过程。最明显的选择是仍然使用typed参数,但传递一些参数来消除函数调用的歧义。

代码语言:javascript
复制
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 (添加实现代码示例,在注释中回答问题):

代码语言:javascript
复制
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 multiply
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/67150226

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档