新手请教:关于 ,@ 在宏中的的用法

我想写一段代码来把一个list中的前缀字符串转换成正则表达式:

(defmacro prefixs-to-reg(prefixs)
  "Convert a list of match-prefex to regex string."
    `(rx bos (or ,@prefixs) eos)))

但宏展开是这样的:

(rx bos
    (or quote
        ("*Man" "magit")))

,@ 没有如文档中说的那样把 list 中的元素展开出来。查了一些资料,但还是没弄明白。

我想问:

  • 上面代码的问题出在哪?忽略了哪些细节?
  • 正确用宏实现该功能应该怎么写?
  • 应该怎么学 elisp ?,写这么一个简单的函数都这么艰难!

调用的时候不要加quote

我那样试过,确实可以,但感觉不是正确的实现方式。没有在其他地方看到那样调用过。

调用的时候不应该加 quote ,你认为没有其他地方这样调用,可能是你没有意识到它们是这样实现的,比如 use-package 中就有这样的:(dired-mode . all-the-icons-dired-mode),这里就不会带 quote

(use-package all-the-icons-dired
    :defer t
    :hook (dired-mode . all-the-icons-dired-mode))

好像确实如此,但我这个函数不是用在这种地方,有办法让它更像函数吗

你可能需要 regexp-opt:

(regexp-opt '("*Man" "magit"))
"\\(?:\\*Man\\|magit\\)"
(rx bos (or "*Man" "magit") eos)
"\\`\\(?:\\*Man\\|magit\\)\\'"

开头和结尾匹配可以直接 concat 糊上去

如果我来写,

(defmacro prefixes-to-reg(&rest prefixs)
  "Convert a list of match-prefex to regex string."
    `(rx bos (or ,@prefixs) eos)))

(prefixes-to-reg "ab" "cc" "fd")

甚至这里就不需要用 defmacro

(defun prefixes-to-reg(&rest prefixs)
  "Convert a list of match-prefex to regex string."
    (rx bos (regex (regexp-opt prefixs)) eos)))

(prefixes-to-reg "ab" "cc" "fd")

问题在于,自己瞎写无所谓,elisp 在正经写包的时候,选择上除非用 defun 做不到和在编译期做魔法,不应该用宏实现功能。

2 个赞

完整看完 elisp intro 之前,不要想着写东西,你问的问题理应自己在 elisp intro 里找解答,甚至我基本可以猜到你连 rx 的 docstring 都没读完就来问问题了,不然看到 evalregex 关键字就该想到换种方法了。

我记得我也这样尝试过,好像也不行。我一会回去再试一下。elisp intro 不太容易看,之前看了下水木社区的《elisp 简明教程》,可能是 elisp 的资料还是太少,自己又不熟悉,遇到问题后,想要找到自己想知道的还是不太容易。

你们都是一步一步看完了的吗?我也不想成为这方面的专家,有没啥捷径,或者比较好的资料?

我直接说吧,我把几千页的 Common Lisp the Language, 近千页的 ANSI Common Lisp,三千页的 ANSI CL 标准都看完了,顺带把 Scheme RnRS 也都扫了,连 MacLisp,Lisp Machine 和 INTERLISP 这些只有考古价值现代电脑上想用都没有的都看了。

从某种意义上,推荐至少看完 elisp intro 我觉得已经算宽松了。从另外一种意义上,如果会手撸自动机,那写个正则也是随手的功夫,根本不用看这么多东西也会写了。

学任何东西都是一步一步来的吧, 这能有什么捷径, 知识又不会自己跑你脑子里去…

这个我很久以前看过, 不如直接看elisp intro

那当然是 ChatGPT 了

没办法,生有涯,知无涯,有其它事情忙。

用得不多,后面尝试着用起来

受教了,术业有专攻,厉害厉害。幸好有这样的社区,有你们这么厉害的人,以后向你们多请教。

标题修改建议:

- 新手请教:能帮忙看下下面这段代码吗?关于 ,@ 在宏中的的用法
+ 新手请教:关于 ,@ 在宏中的的用法

参考: