2016-06-05 16 views
2

Wie erkenne ich, ob eine lexikalische Variable in einem Bereich gebunden ist? Ich möchte grundsätzlich boundp für lexikalische Variablen.Common Lisp: prüfen, ob eine lexikalische Variable existiert?

Konkret sagen, ich habe:

(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."))) 

So boundp prüft korrekt für dynamische Variablen (und Konstanten) und as the hyperspec says, nicht lexikalische Bindungen abdecken.

Aber ich kann kein Äquivalent von boundp für lexikalische Bindungen finden. Wie überprüfe ich sie dann? (Implementation-spezifischen Code für sagen SBCL ist in Ordnung, wenn es nichts tragbares gibt.)

+0

Wofür verwenden Sie das? – melpomene

+0

Ich möchte etwas mehr Sicherheit (gegen Tippfehler usw.) für ein Makro bereitstellen, das mit Variablen arbeitet, einschließlich lexikalischer. (Über das hinaus, was der Compiler bereits tut.) 'Boundp' funktioniert für lexikalische Bindungen in Emacs Lisp, also habe ich bereits einen Emacs-Lisp-Code, der auf diese Weise funktioniert, und möchte ihn auf einfachste und unkomplizierte Weise portieren. – stef

+0

(Hoppla, ich war verwirrt über Emacs Lisp: Wenn "lexikalische Bindung" für eine bestimmte Datei wirksam ist, funktioniert "boundp" hier wie in Common Lisp. Es ist nur so selten in meinem Code, ich tat es nicht merke es mir sogar :))) – stef

Antwort

6

Es gibt nichts wie das in ANSI Common Lisp. Es gibt keinen Zugang zu einer lexikalischen Umgebung. nur

Sie können es auf diese Weise überprüfen:

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> 

Es gibt keine Möglichkeit, einen Namen zu nehmen und sehen, ob es lexikalisch überhaupt gebunden ist. Es ist eine Erweiterung CL, wo die Funktion variable-information würde einige Informationen geben, aber selbst in diesem Fall wäre es wahrscheinlich nicht funktionieren:

* (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 
0

für cltl2: variabler Informationen zu arbeiten, soll es in Makroerweiterung erfolgen Zeit.

(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