[英]How to determine the calling environment?
我試圖隱藏 CL package 中的數學運算符。除了*
、 /
和+
,這工作正常。 然而,這些符號的符號值由實現設置為我在 REPL 中經常使用的值(function 在 SBCL 中是interactive-eval
)。
因為它們是在之前的表單評估中設置的,所以我無法獲取它們,除非在評估表單后通過 CL package 中的符號,即cl:*
。 我考慮過制作*
一個符號宏,如果在 function 上下文中,它將在我的矢量化版本*
上分派,否則返回cl:*
的值。
然而,似乎沒有一種簡單的方法來確定符號是否被用作 function 或值。
到目前為止,我所擁有的程式化版本是:
(in-package :my-math-package)
(setf (fdefinition '+) #'my-vectorised-version-of-+)`
由於我的+
function 版本是 CL 的超集,所以一切正常,除了嘗試在 REPL 中使用*
而在我的 package 中。我可以使用cl:*
並且它有效,但我試圖保持cl:*
和my-package:*
值槽已同步。
符號值的一個類比可能是: (setf (symbol-value '+) #'cl:+)
但這行不通,原因有二:
cl:*
沒有符號值cl:*
當時值的“快照”。 所以我需要動態地保持my-package:*
和cl:*
具有相同的符號值。
有人有主意嗎? 我錯過了一些明顯的東西嗎?
這是 CL 中 package 系統的經典邊緣案例。 然而,對於大多數用途,符號宏將做你想做的事。
例如,如果我在*
不是cl:*
的 package 中,那么我可以這樣說:
(defun * (a b)
(+ a b))
(define-symbol-macro * cl:*)
現在
> (* 1 2)
3
> *
3
> (funcall #'* 3 4)
7
> *
7
這是因為符號宏會影響對值的符號引用,而不是對其 function 定義的引用。
您將失去的是綁定*
並使該綁定變得特殊的能力,因為您無法將符號宏聲明為特殊的。 所以
> (funcall (let ((* 2))
(lambda () *)))
2
例如。 對於*
來說,這可能不是什么大問題。
更重要的是,您還將丟失*
僅用作符號的任何地方。 例如(declare (type (array * (* *)))...)
根本不再起作用。 您對此無能為力,因為這些只是將*
作為符號使用。 這是 package 系統的固有限制。
順便說一句:如果你重載了數字字段的運算符(例如*
和+
),你可能想比人們通常更努力地思考一致性。 或者只是放棄一致性,這似乎是人們通常所做的。 特別是(+)
應返回字段的零,而(*)
應返回字段的 1。 但是……哪個領域?
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.