[英]Expanding macro results in KeyError
使用以下(簡化)代碼:
(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'
我認為宏不應該在編譯時評估 arguments,如果我正確讀取錯誤(我認為我不是)? 基本上,我不想在提供給alias-assign
的每個別名周圍都寫上雙引號,這就是我使用宏的原因。
這是一些更簡單的代碼,它們會產生相同的錯誤:
(setv brew 1)
(defmacro m []
(get (globals) "brew"))
(m)
也許問題現在更明顯了:嘗試在宏擴展期間訪問全局變量brew
不起作用,因為brew
在編譯時不存在,當宏擴展發生時。 如果您只說brew
而不是(get (globals) "brew")
,則會出現同樣的問題,使用NameError
而不是KeyError
。 在任何情況下,表單(setv brew 1)
直到運行時才會被評估。 解決這個問題的一種方法是(eval-when-compile (setv brew 1))
。 這使得評估發生得更早。
一個更廣泛的問題是,由於宏擴展,您似乎正在執行您實際想要返回的代碼。 畢竟,宏的主體是for
,所以它總是返回None
。 與以下代碼對比,它使用引用和取消引用來生成 forms 並返回它們(並使用更新的語法):
(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"}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.