簡體   English   中英

如何判斷調用環境?

[英]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:+)

但這行不通,原因有二:

  1. 編譯時cl:*沒有符號值
  2. 即使有,它也不會有最后評估形式的當前值,它會有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.

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