0

使用以下(简化)代码:

(setv agnostic-manager-installers {})

(defmacro alias-assign [am &rest aliases]
    (for [alias aliases] (assoc
        agnostic-manager-installers
        (str alias)
        (-> (globals) (get (str am)) (get "install")))))

(setv brew {
    "prefix" "/home/linuxbrew/.linuxbrew/"
    "install" (defn brew [] (run
                "curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh | sudo bash"
                :shell True))
})

(alias-assign brew brew homebrew home-brew linuxbrew linux-brew)

我收到以下错误:

Traceback (most recent call last):
  File "/home/shadowrylander/.local/syvl/python/hy/bin/hy", line 8, in <module>
    sys.exit(hy_main())
  File "/usr/lib/python3.9/contextlib.py", line 137, in __exit__
    self.gen.throw(typ, value, traceback)
  File "<stdin>", line 9, in alias_assign
hy.errors.HyMacroExpansionError: 
  File "<stdin>", line 20
    (alias-assign brew brew homebrew home-brew linuxbrew linux-brew)
    ^--------------------------------------------------------------^
expanding macro alias-assign
  KeyError: 'brew'

我认为宏不应该在编译时评估参数,如果我正确读取错误(我不认为我是)?基本上,我不想提供给的每个别名周围都写上双引号alias-assign,这就是我使用宏的原因。

4

1 回答 1

1

这是一些更简单的代码,它们会产生相同的错误:

(setv brew 1)

(defmacro m []
  (get (globals) "brew"))

(m)

也许问题现在更明显了:尝试brew在宏扩展期间访问全局变量不起作用,因为brew在发生宏扩展的编译时不存在。如果你只是说而不是NameError,也会出现同样的问题,而不是。在任何情况下,表单在运行时才会被评估。解决这个问题的一种方法是改为说。这使得评估发生得更早。KeyErrorbrew(get (globals) "brew")(setv brew 1)(eval-when-compile (setv brew 1))

一个更广泛的问题是,由于宏扩展,您似乎正在执行您实际想要返回的代码。毕竟,你的宏的主体是 a for,所以它总是会返回None。对比以下代码,它使用引用和取消引用来生成表单并返回它们(并使用更新的语法):

(setv agnostic-manager-installers {})

(defmacro alias-assign [am #* aliases]
  `(do ~@(gfor
    alias aliases
    `(setv (get agnostic-manager-installers ~(str alias))
      (get ~am "install")))))

(setv brew (dict
  :prefix "/home/linuxbrew/.linuxbrew/"
  :install "placeholder"))

(alias-assign brew brew homebrew home-brew linuxbrew linux-brew)

(print (hy.repr agnostic-manager-installers))

结果是:

{"brew" "placeholder"  "homebrew" "placeholder"  "home-brew" "placeholder"  "linuxbrew" "placeholder"  "linux-brew" "placeholder"}
于 2021-12-27T15:12:04.317 回答