【问题标题】:Common Lisp: check if lexical variable exists?Common Lisp:检查词法变量是否存在?
【发布时间】:2016-06-05 15:53:19
【问题描述】:

如何检测词法变量是否绑定在范围内?我基本上想要boundp 作为词法变量。

具体来说,说我有:

(defvar *dynamic* 1)
(defconstant +constant+ 2)

(let ((lexical 3))
  (when (boundp '*dynamic*)  ; t
    (print "*dynamic* bound."))
  (when (boundp '+constant+) ; t
    (print "+constant+ bound."))
  (when (boundp 'lexical)    ; nil
    (print "lexical bound.")))

所以boundp 正确检查动态变量(和常量),而as the hyperspec says 不包括词法绑定。

但我找不到任何与 boundp 等效的词法绑定。那么我该如何检查它们呢? (如果没有任何可移植的东西,那么 SBCL 的实现特定代码就可以了。)

【问题讨论】:

  • 你打算用它做什么?
  • 我想为对变量(包括词法变量)进行操作的宏提供一些额外的安全性(防止拼写错误等)。 (超出了编译器已经做的事情。)boundp 用于 Emacs Lisp 中的词法绑定,所以我已经有一些 Emacs Lisp 代码可以以这种方式工作,并希望以最简单直接的方式移植它。
  • (哎呀,我对 Emacs Lisp 感到困惑:如果 lexical-binding 对给定文件有效,boundp 就像在 Common Lisp 中一样工作。它在我的代码中很少有效,我什至没有注意到。:))

标签: scope common-lisp


【解决方案1】:

在 ANSI Common Lisp 中没有类似的东西。无法访问词法环境。

你只能这样检查:

CL-USER 8 > (let ((lexical 3))
              (when (ignore-errors lexical) 
                (print "lexical bound."))
              (values))

"lexical bound." 

CL-USER 9 > (let ((lexical 3))
              (when (ignore-errors lexxxical) 
                (print "lexical bound."))
              (values))
<nothing>

没有办法取一个名字,看看它是否在词法上是完全绑定的。 CL 有一个扩展,函数variable-information 会提供一些信息,但即使在这种情况下它也可能不起作用:

* (require "sb-cltl2")

("SB-CLTL2")
* (apropos "variable-information")

VARIABLE-INFORMATION
SB-CLTL2:VARIABLE-INFORMATION (fbound)
* (let ((lexical 3))
     (sb-cltl2:variable-information 'lexical))
; in: LET ((LEXICAL 3))
;     (LET ((LEXICAL 3))
;       (SB-CLTL2:VARIABLE-INFORMATION 'LEXICAL))
; 
; caught STYLE-WARNING:
;   The variable LEXICAL is defined but never used.
; 
; compilation unit finished
;   caught 1 STYLE-WARNING condition

NIL
NIL
NIL

【讨论】:

    【解决方案2】:

    为了使 cltl2:variable-information 起作用,它应该在宏扩展时间内完成。

    (ql:quickload :introspect-environment)
    (use-package :introspect-environment) ;; also exports cltl2 functions.
    
    (defmacro in-compile-time ((environment) &body body &environment env)
      (check-type environment symbol)
      (eval `(let ((,environment ,env)) (progn ,@body)))
      nil) ; does not affect the expansion
    
    (defun fn ()
      (let ((lexical 2))
        (in-compile-time (env)
          (print (introspect-environment:variable-information 'lexical env))
          (print (introspect-environment:variable-information 'lexxxxical env)))))
    ; compiling (DEFUN FN ...)
    :LEXICAL 
    NIL 
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-06-18
      • 2015-04-04
      • 1970-01-01
      • 2013-07-04
      • 2014-09-08
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多