Nim 宏:如何命名正文参数

如何解决Nim 宏:如何命名正文参数

我一直在尝试制作 Neel 的更改版本,它使用 Jester 并添加了功能。在注册了一些可以方便地从前端调用的程序后,您可以使用一个名为 startApp 的宏启动 Neel 应用程序,该宏具有以下签名:

macro startApp*(startURL,assetsDir: string,portNo: int = 5000,position: array[2,int] = [500,150],size: array[2,int] = [600,600],chromeFlags: seq[string] = @[""],appMode: bool = true) =
...

startApp 创建一个带有 router 宏和一些硬编码路由的 Jester 路由器:

router theRouter:
  get "/":
    resp(Http200,NOCACHE_HEADER,readFile(getCurrentDir() / `assetsDir` / startURL`))#is this most efficient?
  get "/neel.js":
    ...

现在我一直在尝试修改它并添加一个参数以允许 startApp 的调用者通过一个无类型的“body”类型的参数传入额外的路由(是否有一个名称,通过路?),就像这样:

macro startApp*(startURL,appMode: bool = true,extraRoutes : untyped
               )=

...所以你可以这样做

startApp(startUrl="index.html",assetsDir="web",appMode=false):
  get "/extra.js":
    resp(Http200,`noCacheHeader`,"console.log('loaded extra.js')")
  post "/login":
    ...

但是现在上面的代码导致了一个错误

Error: type mismatch: got <string,void>
but expected one of: 
proc get[T](self: Option[T]): lent T
first type mismatch at position: 1

这意味着编译器正在尝试评估 get 表达式,而不是简单地将其未处理的语法树传递到 startApp 中,这与无类型宏参数的整点相反。我发现如果传递所有参数,它就可以正常工作。所以我想我没有命名身体的事实导致 Nim 认为我必须尝试将它传递给 portNo 或其他东西。很公平。但是我现在该怎么办?有什么办法可以像 extraRoutes=... 一样吗?我尝试执行 extraRoutes=quote do: ... 和类似的操作,但找不到任何有效的方法。

所以……这能解决吗?或者我是否必须像手动传递默认参数的副本那样进行黑客攻击?

如果您有更好的想法来实现这一点,我很乐意,但请详细说明。我总共花了大约五个小时,我已经尝试过例如事先制作了一个 StmtList 而不是将这个额外的路由业务捆绑在 startApp 中,但放弃了,因为错误更加神秘。

解决方法

解决方案 1

默认参数可以传递给宏,但对于块来说,它似乎不是特别漂亮:

import std/macros

macro optArgs(arg1: static[string],arg2: static[string] = "hello",arg3: typed = nil,body: untyped = nil) =
  if not isNil(body):
    echo body.treeRepr()


optArgs(
  "test",body = (
    quote do:
      some untyped arguments that are not checked
  )
)

optArgs("test")
optArgs("test",arg3 = int)
optArgs("test",body = int)

输出

Call
  Ident "quote"
  StmtList
    Command
      Command
        Ident "some"
        Command
          Ident "untyped"
          Command
            Ident "arguments"
            Command
              Ident "that"
              Ident "are"
      Prefix
        Ident "not"
        Ident "checked"
NilLit
NilLit
Ident "int"

如果您想使用 call(<arguments>): body 语法传递代码块,我建议采用以下方法:接受元组的语法(可以混合位置参数和命名参数)并自己进行一些后处理。在这种特殊情况下,您将获得 (Par (Ident "positional") (ExprColonExpr (Ident "test") (IntLit 123))) 作为参数列表,可以对其进行处理以获得必要的参数,或者您可以调用 error 以指示误用。

macro namedArgs(arglist: untyped,body: untyped) =
  echo argList.lispRepr()
  
namedArgs (positional,test: 123):
  echo "ACtual body"

解决方案 2

应该注意的一件事是,如果参数传递不正确(如 Error: undeclared identifier: 'positional'),类似元组的参数方法会产生相当神秘的错误。这可以使用

修复
macro vras(arglist: varargs[untyped]) =
  echo argList.lispRepr()
  
vras(positional,test = 123):
  echo "ACtual body"

结果为您提供了以下树,但在这种情况下,您必须手动实现所有参数处理。

Arglist
  Ident "positional"
  ExprEqExpr
    Ident "test"
    IntLit 123
  StmtList
    Command
      Ident "echo"
      StrLit "ACtual body"

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams[&#39;font.sans-serif&#39;] = [&#39;SimHei&#39;] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -&gt; systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping(&quot;/hires&quot;) public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate&lt;String
使用vite构建项目报错 C:\Users\ychen\work&gt;npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-
参考1 参考2 解决方案 # 点击安装源 协议选择 http:// 路径填写 mirrors.aliyun.com/centos/8.3.2011/BaseOS/x86_64/os URL类型 软件库URL 其他路径 # 版本 7 mirrors.aliyun.com/centos/7/os/x86
报错1 [root@slave1 data_mocker]# kafka-console-consumer.sh --bootstrap-server slave1:9092 --topic topic_db [2023-12-19 18:31:12,770] WARN [Consumer clie
错误1 # 重写数据 hive (edu)&gt; insert overwrite table dwd_trade_cart_add_inc &gt; select data.id, &gt; data.user_id, &gt; data.course_id, &gt; date_format(
错误1 hive (edu)&gt; insert into huanhuan values(1,&#39;haoge&#39;); Query ID = root_20240110071417_fe1517ad-3607-41f4-bdcf-d00b98ac443e Total jobs = 1
报错1:执行到如下就不执行了,没有显示Successfully registered new MBean. [root@slave1 bin]# /usr/local/software/flume-1.9.0/bin/flume-ng agent -n a1 -c /usr/local/softwa
虚拟及没有启动任何服务器查看jps会显示jps,如果没有显示任何东西 [root@slave2 ~]# jps 9647 Jps 解决方案 # 进入/tmp查看 [root@slave1 dfs]# cd /tmp [root@slave1 tmp]# ll 总用量 48 drwxr-xr-x. 2
报错1 hive&gt; show databases; OK Failed with exception java.io.IOException:java.lang.RuntimeException: Error in configuring object Time taken: 0.474 se
报错1 [root@localhost ~]# vim -bash: vim: 未找到命令 安装vim yum -y install vim* # 查看是否安装成功 [root@hadoop01 hadoop]# rpm -qa |grep vim vim-X11-7.4.629-8.el7_9.x
修改hadoop配置 vi /usr/local/software/hadoop-2.9.2/etc/hadoop/yarn-site.xml # 添加如下 &lt;configuration&gt; &lt;property&gt; &lt;name&gt;yarn.nodemanager.res