簡體   English   中英

擴展宏導致 KeyError

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM