Am I missing some important fact about interning s

2019-02-27 19:19发布

问题:

To be brief. Here is my several tries to intern and use a symbol in clisp.

 [1]> (setq sym (intern "foo"))
 |foo|
 [2]> (eq sym 'foo)
 NIL

Why???

 [3]> (defun internup (me &optional (package *package*))
   (intern (string-upcase me) package))
 INTERNUP

 [4]> (eq 'abc (internup "abc"))
 T

Probably must be upcase.

 [12]>(let ((abc 2))
   (eval '(+ 2 abc)))

 *** - EVAL: variable ABC has no value
 The following restarts are available:

ok

 [18]> (let ((abc 2))
 (eval '(+ 2 'abc)))

 *** - +: ABC is not a number
 The following restarts are available:

Interesting. Should I set it before.

 [14]> (setq a (internup "abc"))
 ABC

 [15]> (let ((abc 2))
 (eval '(+ 2 a)))

 *** - +: ABC is not a number
 The following restarts are available:

And again wrong. Hmm I must be missing some important fact about interning symbols in LISP. Can you help me ?

回答1:

Your problem has nothing to do with interning.

The first problem is indeed causes by the fact that the reader will always uppercase the symbols, so you need to call (intern "FOO") in order to get the same result as 'foo.

The problem with EVAL is caused by the fact that LET introduces a lexical binding which is not visible inside EVAL. If you really want this to work you'd have to declare abc to be special, like so:

(let ((abc 2))
    (declare (special abc))
    (eval '(1+ abc)))

A special declaration will cause the variable to have dynamic binding, instead of lexical binding (the latter means that the binding is limited to the local lexical context, i.e. within the LET form. With the special declaration the variable is available to anything that is called by from that form).

Note that the use of both special declarations and eval is something you should be very careful about and you should probably rethink your use of EVAL in the first place. It is very rare that you actually need to use it. In most cases you're actually looking for the use of lambda functions instead.



回答2:

Eval evaluates the form in the null lexical environment, i.e. with no lexical bindings. That has nothing to do with the interning of symbols.



回答3:

The case-sensitivity of the Common Lisp reader is determined by the readtable:

(readtable-case *readtable*)

Typically the reader will initially intern symbols in uppercase (unless you explicitly escape characters). Hence:

(eq (intern "foo") 'foo) => NIL

(eq (intern "FOO") 'foo) => T

(eq (intern "FOo") 'fo\o) => T

You can use backquote syntax to build the form for eval:

(let ((abc 2))
  (eval `(+ 2 ,abc)))

=> 4



标签: lisp symbol