2017-05-23 3 views
2

Ou autrement dit: Est-il possible pour une variable CL ne pas être (en partie) un symbolele X dans (LET ((x ...) un symbole entièrement étoffées

je pense? Je peux avoir une idée fausse profonde sur les variables dans CL.

J'ai toujours pensé CL n'a pas de variables, seuls les symboles et symboles ont (entre autres propriétés) un nom et une cellule de valeur (qui est la variable).
et quand quelqu'un a dit "variable x a la valeur 42" Je pensais que c'était court pour "la cellule de valeur du symbole nommé x sto res la valeur 42 ".

Mais c'est probablement faux.

Lorsque je tape

> (let ((a 42)) 
     (type-of 'a)) 
SYMBOL 
; caught STYLE-WARNING: 
; The variable A is defined but never used. 

est la variable lexicale a dans cet exemple un symbole entièrement étoffées dont la cellule valeur a été fixée à 42? Parce que l'avertissement The variable A is defined but never used suggère le contraire et il semble que la variable lexicale ne soit pas la même chose que le symbole a sous la forme (type-of 'a) suivante

Répondre

5

Common Lisp dispose de deux types de données qui ont une signification particulière pour l'évaluation:

  • cellules cons/listes -> utilisé dans le code source Lisp, les listes sont des formes Lisp
  • symboles -> utilisé comme noms à diverses fins

Si vous souhaitez les utiliser comme données dans le code Lisp, alors vous devez te les.

Les deux sont utilisés dans le code source Lisp, mais une fois que vous compilez le code, ils peuvent disparaître.

Les variables sont écrites en tant que symboles dans le code source. Mais dans le code compilé, ils peuvent disparaître - quand ils sont variables lexicales.

Exemple d'utilisation SBCL:

un fichier avec

(defun test (foo) 
    (+ foo foo)) 

Maintenant nous faisons:

CL-USER> (proclaim '(optimize (debug 0))) ; the compiler saves no debug info 
; No value 
CL-USER> (compile-file "/tmp/test.lisp") 
; compiling file "/private/tmp/test.lisp" (written 23 MAY 2017 09:06:51 PM): 
; compiling (DEFUN TEST ...) 

; /tmp/test.fasl written 
; compilation finished in 0:00:00.013 
#P"/private/tmp/test.fasl" 
NIL 
NIL 
CL-USER> (find-symbol "FOO") 
FOO 
:INTERNAL 

Le compilateur a lu le code source et créé une compilation FASL fichier. Nous voyons que le symbole FOO est maintenant dans le paquet actuel. FOO nomme la variable dans notre code source.

Quittez maintenant SBCL et redémarrez-le.

Chargeons le code de la machine:

CL-USER> (load "/tmp/test") 
T 
CL-USER> (find-symbol "FOO") 
NIL 
NIL 

Il n'y a pas de symbole plus FOO. Il n'est pas non plus possible de récupérer la valeur lexicale de la variable FOO en utilisant le symbole FOO. Il n'y a pas de mappage (comme une sorte d'environnement lexical explicite) de symboles à des valeurs lexicales.

4

La cellule de valeur est utilisée pour les variables dynamiques (AKA "spéciales"), et non pour les variables lexicales. Les variables lexicales sont des symboles dans le code source, mais elles n'ont aucune relation d'exécution avec le symbole (sauf pour une utilisation interne par le débogueur).

Donc, si vous avez écrit:

(let ((a 42)) 
    (declare (special a)) 
    (print (symbol-value 'a))) 

cela fonctionnerait parce que la déclaration en fait une variable dynamique, et vous pouvez accéder à la valeur dans la cellule de fonction.

+0

Cela signifie-t-il que les variables lexicales créées par 'defun',' lambda', 'let', etc. semblent être des symboles mais, une fois compilées, ne le sont pas? – Frank

+1

Ce ne sont que des symboles dans le code source, tout comme les appels de fonction sont des listes dans le code source. Quand ils sont compilés, tout se transforme en code machine, et les variables lexicales ne sont que des emplacements de pile. – Barmar

2

Vous ne vérifiez pas le type de la variable liée a ou sa valeur, mais celle d'un symbole constant littéral qui arrive à avoir le même nom que la variable dans votre formulaire let:

(let ((a 42)) 
    (type-of 'literal-symbol)) 
; ==> symbol (since 'literal-symbol evaluates to a symbol, just like 'a does) 

Pour vérifier la type de la valeur de la liaison a vous le faites sans la citation littérale:

(let ((a 42)) 
    (type-of a)) 
; ==> (integer 0 281474976710655) 

ici vous vérifier réellement le type de Apprécions lié et il est un entier. Surpris que 42 est un nombre et non un symbole?

(let ((a 10) (b 'a)) 
    (list a b)) 
; ==> (10 a) 

La variable a et le littéral 'a cité ne sont pas les mêmes. Ils ont l'air de se ressembler lorsqu'ils sont affichés, mais 'a est le code et a est le code. Dans CL un compilateur peut utiliser des listes et des symboles en interne, mais ce qu'il est lorsque son exécution est entièrement à l'implémentation et dans la plupart des implémentations qu'ils empilent quand ils le peuvent et le code qui évalue une variable allouée par pile serait remplacé par quelque chose valeur à l'index de la pile. CL a une fonction disassemble et si vous vérifiez la sortie dans SBCL à partir de quelque chose, vous verrez qu'il est plus similaire à la sortie d'un compilateur C que la source Lisp d'origine.

+0

démonter est vraiment intéressant! Je vous remercie – Frank