CLHS 记录:10.符号

10. 符号

10.1 符号概念

下面这段列出了一些可应用于符号属性列表的已定义的名字.

get  remprop  symbol-plist  

Figure 10-1. 属性列表已定义的名字

下一段列出了一些可应用于创建和查询符号的已定义名字.

copy-symbol  keywordp     symbol-package  
gensym       make-symbol  symbol-value    
gentemp      symbol-name                  

Figure 10-2. 符号创建和查询的已定义名字

10.2 符号字典

系统类 SYMBOL

  • 类优先级列表(Class Precedence List):

    symbol, t
    
  • 描述(Description):

    符号被用于它们的对象标识来命名 Common Lisp 中不同的实体, 包括 (但不限于) 像变量和函数这样的语言实体.
    
    符号可以被一起收集到包中. 如果一个符号在一个包中是可访问的就是那个符号被捕捉到那个包中; 相同符号可以被捕捉到不止一个包中. 如果一个符号没有被捕捉到任何包中, 就说它是未捕捉的.
    
    一个被捕捉的符号在它是可访问的任何包中通过它的名称是唯一可识别的.
    
    符号有着以下属性. 出于历史原因, 它们有时作为 cell 被引用, 虽然符号和它们的属性的实际内部表示是依赖于具体实现的.
    
    Name
    
        一个符号的名字是用于标识这个符号的一个字符串. 每个符号有一个名字, 如果那个名字被修改那么结果是未定义的. 这个名字被用作这个符号的外部的, 打印的表示部分; 见章节 2.1 (Character Syntax). 函数 symbol-name 返回一个给定符号的名字. 一个符号的名字中可能有任何字符.
    
    Package
    
        在这个 cell 的这个对象被称为这个符号的 home 包. 如果这个 home 包是 nil, 那么这个符号有时就说是没有 home 包.
    
        当一个符号被首次创建, 它没有 home 包. 当它被第一次捕捉时, 最初被捕捉所在包称为它的 home 包. 一个符号的 home 包可以通过函数 symbol-package 来访问.
    
        如果一个符号从它的 home 包中被解除捕捉, 它的 home 包会被设置为 nil. 这个符号可能或可能不是一个未被捕捉的符号取决于这里是否存在另一个包捕捉了这个符号. 一个没有 home 包的符号显然因此被称为是未被捕捉的.
    
        如果尝试去修改在 COMMON-LISP 包或者 KEYWORD 包中的一个符号的 home 包那么结果是未定义的.
    
    Property list
    
        一个符号的属性列表为关联已命名属性和那个符号提供了一个机制. 关于添加和移除的操作对于这个属性列表是破坏性的. Common Lisp 为直接操作属性列表对象 (比如, see getf, remf, 和 symbol-plist) 以及通过对这个符号的引用来隐式操作一个符号的属性列表 (比如, 见 get 和 remprop) 都提供了操作符. 和一个新的符号关联的属性列表被初始化为 null.
    
    Value
    
        如果一个符号有一个值属性, 它就被称为是绑定的, 并且这个事实可以通过函数 boundp 来被检测. 被包含在一个绑定的符号的值 cell 中的对象是那个符号命名的全局变量的值, 并且可以通过函数 symbol-value 来访问. 一个符号可以通过函数 makunbound 变得是未绑定的.
    
        如果尝试去修改一个命名一个常变量的符号的值或者使这样一个符号变为未绑定的, 那么后果是未定义的.
    
    Function
    
        如果一个符号有一个函数属性, 它就被称为是 fbound 的, 并且这个事实可以通过函数 fboundp 来检测. 如果这个符号是一个全局环境中的函数的名字, 这个函数 cell 就包含了那个函数, 并且可以通过函数 symbol-function 来访问. 如果这个符号是全局环境中的一个宏 (见 macro-function) 或者一个特殊操作符 (见 special-operator-p) 的名字, 那么这个符号就是 fbound 的, 并且可以通过函数 symbol-function 来访问, 但是那个函数 cell 所包含的对象的类型和目的是依赖于具体实现. 一个符号可以通过函数 fmakunbound 来变为 funbound 的.
    
        如果尝试去修改命名一个特殊表达式形式的符号的函数值, 那么后果是未定义的.
    
    在一个符号的值 cell 和函数 cell 上的操作有时被描述为对符号自身的影响, 但是用户应该注意在那些 cell 的内容和全局变量或全局函数定义之间分别存在一个紧密的关系.
    
    符号被用作词法变量和词法函数定义的标识, 但是在那个角色中<!--TODO but in that role ??-->, 只有它们的对象标识是有意义的. Common Lisp 没有在一个符号上提供在一个词法变量或一个词法函数定义上有任何效果的操作符.
    
  • 也见(See Also):

    Section 2.3.4 (Symbols as Tokens), Section 2.3.1.1 (Potential Numbers as Tokens), Section 22.1.3.3 (Printing Symbols)
    

类型 KEYWORD

  • 超类型(Supertypes):

    keyword, symbol, t
    
  • 描述(Description):

    类型 keyword 包括所有被捕捉在 KEYWORD 包的符号.
    
    捕捉一个符号到 KEYWORD 包中有三个必然的影响:
    
    1. 它导致这个符号被绑定到它自身.
    2. 它导致这个符号变为这个 KEYWORD 包的外部符号.
    3. 它导致这个符号变为一个常变量.
    
  • 也见(See Also):

    keywordp
    

函数 SYMBOLP

  • 语法(Syntax):

    symbolp object => generalized-boolean
    
  • 参数和值(Arguments and Values):

    object---一个对象.
    generalized-boolean---一个广义的 boolean.
    
  • 描述(Description):

    如果对象 object 是 symbol 类型的就返回 true; 否则, 返回 false.
    
  • 示例(Examples):

    (symbolp 'elephant) =>  true
    (symbolp 12) =>  false
    (symbolp nil) =>  true
    (symbolp '()) =>  true
    (symbolp :test) =>  true
    (symbolp "hello") =>  false
  • 副作用(Side Effects): None.

  • 受此影响(Affected By): None.

  • 异常情况(Exceptional Situations): None.

  • 也见(See Also):

    keywordp, symbol, typep
    
  • 注意(Notes):

    (symbolp object) ==  (typep object 'symbol)
    

    函数 KEYWORDP

    • 语法(Syntax):

      keywordp object => generalized-boolean

    • 参数和值(Arguments and Values):

      object—一个对象.
      generalized-boolean—一个广义 boolean.

    • 描述(Description):

      如果对象 object 是一个关键字就返回 true; 否则, 返回 false.

    • 示例(Examples):

      (keywordp 'elephant) =>  false
      (keywordp 12) =>  false
      (keywordp :test) =>  true
      (keywordp ':test) =>  true
      (keywordp nil) =>  false
      (keywordp :nil) =>  true
      (keywordp '(:test)) =>  false
      (keywordp "hello") =>  false
      (keywordp ":hello") =>  false
      (keywordp '&optional) =>  false
    • 副作用(Side Effects): None.

    • 受此影响(Affected By): None.

    • 异常情况(Exceptional Situations): None.

    • 也见(See Also):

      constantp, keyword, symbolp, symbol-package

    • 注意(Notes): None.

函数 MAKE-SYMBOL

  • 语法(Syntax):

    make-symbol name => new-symbol
    
  • 参数和值(Arguments and Values):

    name---一个字符串.
    new-symbol---一个新的, 未被捕捉的符号.
    
  • 描述(Description):

    make-symbol 创建并返回一个新的, 未捕捉的名为给定名字 name 的符号. 这个新的符号 new-symbol 既没有被绑定也没有被 fbound 并且有一个 null 属性列表.
    
    成为这个新符号 new-symbol 的名字的字符串是那个给定的名字 name 还是它的拷贝是依赖于具体实现的. 一旦一个字符串已经被给定作为给 make-symbol 的 name 参数, 如果后面去修改这个字符串那么后果是未定义的.
    
  • 示例(Examples):

    (setq temp-string "temp") =>  "temp"
    (setq temp-symbol (make-symbol temp-string)) =>  #:|temp|
    (symbol-name temp-symbol) =>  "temp"
    (eq (symbol-name temp-symbol) temp-string) =>  implementation-dependent
    (find-symbol "temp") =>  NIL, NIL
    (eq (make-symbol temp-string) (make-symbol temp-string)) =>  false
  • 副作用(Side Effects): None.

  • 受此影响(Affected By): None.

  • 异常情况(Exceptional Situations):

    如果名字 name 不是一个字符串那么应该发出一个 type-error 类型的错误.
    
  • 也见(See Also):

    copy-symbol
    
  • 注意(Notes):

    make-symbol 不会尝试去转换这个名字的大小写为大写的. 对于符号发生的仅有的大小写转换是通过 Lisp 读取器完成的. 对于符号创建的编程接口保留大小写, 并且对于捕捉符号的编程接口是大小写敏感的.
    

函数 COPY-SYMBOL

  • 语法(Syntax):

    copy-symbol symbol &optional copy-properties => new-symbol
    
  • 参数和值(Arguments and Values):

    symbol---一个符号.
    copy-properties---一个广义的 boolean. 默认是 false.
    new-symbol---一个新的, 未捕捉的符号.
    
  • 描述(Description):

    copy-symbol 返回一个新的, 未被捕捉的符号, 它的名字和给定符号的名字是 string= 的或者可能是一样的.
    
    如果 copy-properties 是 false, 这个新符号 new-symbol 即没有被绑定也没有被 fbound 并且有一个 null 属性列表. 如果 copy-properties 是 true, 那么这个新符号 new-symbol 的初始值是那个符号 symbol 的值, 这个新符号的初始函数定义是那个符号 symbol 的函数值, 并且那个新符号 new-symbol 的属性列表是符号 symbol 的属性列表的一个拷贝.
    
  • 示例(Examples):

    (setq fred 'fred-smith) =>  FRED-SMITH
    (setf (symbol-value fred) 3) =>  3
    (setq fred-clone-1a (copy-symbol fred nil)) =>  #:FRED-SMITH
    (setq fred-clone-1b (copy-symbol fred nil)) =>  #:FRED-SMITH
    (setq fred-clone-2a (copy-symbol fred t))   =>  #:FRED-SMITH
    (setq fred-clone-2b (copy-symbol fred t))   =>  #:FRED-SMITH
    (eq fred fred-clone-1a) =>  false
    (eq fred-clone-1a fred-clone-1b) =>  false
    (eq fred-clone-2a fred-clone-2b) =>  false
    (eq fred-clone-1a fred-clone-2a) =>  false
    (symbol-value fred) =>  3
    (boundp fred-clone-1a) =>  false
    (symbol-value fred-clone-2a) =>  3
    (setf (symbol-value fred-clone-2a) 4) =>  4
    (symbol-value fred) =>  3
    (symbol-value fred-clone-2a) =>  4
    (symbol-value fred-clone-2b) =>  3
    (boundp fred-clone-1a) =>  false
    (setf (symbol-function fred) #'(lambda (x) x)) =>  #<FUNCTION anonymous>
    (fboundp fred) =>  true
    (fboundp fred-clone-1a) =>  false
    (fboundp fred-clone-2a) =>  false
  • 副作用(Side Effects): None.

  • 受此影响(Affected By): None.

  • 异常情况(Exceptional Situations):

    如果 symbol 不是一个符号, 那么应该发出一个 type-error 类型的错误.
    
  • 也见(See Also):

    make-symbol
    
  • 注意(Notes):

    鼓励实现者不要去拷贝那个没有必要是那个符号的名字的字符串. 除非这里有一个好的理由去做这个, 对于这个新符号 new-symbol 的名字的正常的具体实现策略是和给定符号 symbol 的名字是相同的.
    

函数 GENSYM

  • 语法(Syntax):

    gensym &optional x => new-symbol
    
  • 参数和值(Arguments and Values):

    x---一个字符串或者一个非负整数. Complicated defaulting behavior; 见下文.
    new-symbol---一个新的, 未捕捉的符号.
    
  • 描述(Description):

    创建并返回一个新的, 未捕捉的符号, 就像是通过调用 make-symbol 的一样. (gensym 和 make-symbol 仅有的区别是如何决定这个新符号 new-symbol 的名字.)
    
    这个新符号 new-symbol 的名字由一个默认为 "G" 的前缀和一个默认为 *gensym-counter* 的值的数字表示拼接而成.
    
    如果提供了 x, 并且是一个字符串, 那么这个字符串仅在这个对 gensym 的调用中替换 "G" 作为前缀.
    
    如果提供了 x, 并且是一个整数, 那么这个整数仅在这个对 gensym 的调用中替换 *gensym-counter* 的值被用作后缀.
    
    当且仅当没有提供显式前缀时, *gensym-counter* 在它被使用后递增.
    
  • 示例(Examples):

    (setq sym1 (gensym)) =>  #:G3142
    (symbol-package sym1) =>  NIL
    (setq sym2 (gensym 100)) =>  #:G100
    (setq sym3 (gensym 100)) =>  #:G100
    (eq sym2 sym3) =>  false
    (find-symbol "G100") =>  NIL, NIL
    (gensym "T") =>  #:T3143
    (gensym) =>  #:G3144
  • 副作用(Side Effects):

    可能递增 *gensym-counter*.
    
  • 受此影响(Affected By):

    *gensym-counter*
    
  • 异常情况(Exceptional Situations):

    如果 x 不是一个字符串也不是一个非负整数, 那么应该发出一个 type-error 类型的错误.
    
  • 也见(See Also):

    gentemp, *gensym-counter*
    
  • 注意(Notes):

    传递一个数字参数给 gensym 的能力已经被废弃了; 显示绑定 *gensym-counter* 目前语法上是首选的. (关于可选参数的一些巴洛克式的惯例本质上是历史性的, 并且主要是为了支持较老版本的 Lisp 方言的兼容性. 在现代代码中, 建议仅有的参数种类是一个字符串前缀. 通常, 为了获取这个新符号 new-symbol 的名字的更灵活的控制, 考虑使用 make-symbol.)
    

变量 GENSYM-COUNTER

  • 值类型(Value Type):

    一个非负整数.
    
  • 初始值(Initial Value):

    依赖于具体实现.
    
  • 描述(Description):

    用来构造由函数 gensym 生成的下一个符号的名字的一个数字.
    
    *gensym-counter* 可以在任何时间被赋值或绑定, 但是它的值必须总是为一个非负整数.
    
  • 示例(Examples): None.

  • 受此影响(Affected By):

    gensym.
    
  • 也见(See Also):

    gensym
    
  • 注意(Notes):

    传递一个数字参数给 gensym 的能力已经被废弃了; 显示绑定 *gensym-counter* 目前语法上是首选的.
    

函数 GENTEMP

  • 语法(Syntax):

    gentemp &optional prefix package => new-symbol
    
  • 参数和值(Arguments and Values):

    prefix---一个字符串. 默认为 "T".
    package---一个包标识符. 默认是当前包.
    new-symbol---一个新的, 被捕捉的符号.
    
  • 描述(Description):

    gentemp 创建并返回一个新的符号, 被捕捉在指定的包中. 这个符号保证是一个之前在包 package 中无法访问的. 它既没有被绑定也没有被 fbound, 并且有一个 null 属性列表.
    
    这个新符号 new-symbol 的名字是一个前缀和后缀拼接而成, 这个后缀由一个只有 gentemp 使用的内部计数器获取. (如果这个名字的一个符号在包 package 中已经是可以访问的, 这个计数器每次有必要产生一个之前在这个包 package 中不是一个可访问符号的名字就会被递增.)
    
  • 示例(Examples):

    (gentemp) =>  T1298
    (gentemp "FOO") =>  FOO1299
    (find-symbol "FOO1300") =>  NIL, NIL
    (gentemp "FOO") =>  FOO1300
    (find-symbol "FOO1300") =>  FOO1300, :INTERNAL
    (intern "FOO1301") =>  FOO1301, :INTERNAL
    (gentemp "FOO") =>  FOO1302
    (gentemp) =>  T1303
  • 副作用(Side Effects):

    它的内部计数器被递增不止一次.
    在包 package 中捕捉这个新符号 new-symbol.
    
  • 受此影响(Affected By):

    它的内部计数器的当前状态, 以及这个包 package 的当前状态.
    
  • 异常情况(Exceptional Situations):

    如果前缀不是一个字符串那么应该发出一个 type-error 类型的错误. 如果包 package 不是一个包标识符那么应该发出一个 type-error 类型的错误.
    
  • 也见(See Also):

    gensym
    
  • 注意(Notes):

    函数 gentemp 被废弃了.
    
    如果包 package 是 KEYWORD 包, 那么结果是包 package 的一个外部符号. 否则, 结果就是一个包 package 的一个内部符号.
    
    这个 gentemp 内部计数器不依赖于被 gensym 使用的计数器 *gensym-counter*. 这里没有用于访问这个 gentemp 内部计数器的措施.
    
    只是因为 gentemp 创建一个之前不存在的符号并不意味着这样一个符号在未来可能是不可见的 (比如, 在一个数据文件中---可能由另一个会话中的相同程序创建). 因此, 这个符号并不是真正独特的就像 gensym 一样. 特别地, 自动代码生成的程序应该注意不要将全局属性附加到这些生成的符号上 (比如, special 声明) 并且把它们写道一个文件中, 因为这样的全局属性可能在不同的会话中, 最终会应用到其他符号上, 这些符号是在另一天自动生成用于其他目的.
    

访问器 SYMBOL-FUNCTION

  • 语法(Syntax):

    symbol-function symbol => contents
    
    (setf (symbol-function symbol) new-contents)
    
  • 参数和值(Arguments and Values):

    symbol---一个符号.
    
    contents--- 如果这个符号 symbol 是一个全局定义的宏或者特殊操作符, 那么就返回一个依赖于具体实现的性质和标识的对象. 如果这个符号 symbol 没有被全局定义为一个宏或一个特殊操作符, 并且这让个符号 symbol 被 fbound 了, 返回一个函数对象.
    
    new-contents---一个函数.
    
  • 描述(Description):

    访问这个符号的函数 cell.
    
  • 示例(Examples):

    (symbol-function 'car) =>  #<FUNCTION CAR>
    (symbol-function 'twice) is an error   ;because TWICE isn't defined.
    (defun twice (n) (* n 2)) =>  TWICE
    (symbol-function 'twice) =>  #<FUNCTION TWICE>
    (list (twice 3)
          (funcall (function twice) 3)
          (funcall (symbol-function 'twice) 3))
    =>  (6 6 6)
    (flet ((twice (x) (list x x)))
      (list (twice 3)
            (funcall (function twice) 3)
            (funcall (symbol-function 'twice) 3)))
    =>  ((3 3) (3 3) 6)   
    (setf (symbol-function 'twice) #'(lambda (x) (list x x)))
    =>  #<FUNCTION anonymous>
    (list (twice 3)
          (funcall (function twice) 3)
          (funcall (symbol-function 'twice) 3))
    =>  ((3 3) (3 3) (3 3))
    (fboundp 'defun) =>  true
    (symbol-function 'defun)
    =>  implementation-dependent
    (functionp (symbol-function 'defun))
    =>  implementation-dependent
    (defun symbol-function-or-nil (symbol)
      (if (and (fboundp symbol)
                (not (macro-function symbol))
                (not (special-operator-p symbol)))
          (symbol-function symbol)
          nil)) =>  SYMBOL-FUNCTION-OR-NIL
    (symbol-function-or-nil 'car) =>  #<FUNCTION CAR>
    (symbol-function-or-nil 'defun) =>  NIL
  • 副作用(Side Effects): None.

  • 受此影响(Affected By):

    defun
    
  • 异常情况(Exceptional Situations):

    如果 symbol 不是一个符号那么应该发出一个 type-error 类型的错误.
    
    如果 symbol 没有被 fbound 并且尝试去读取它的定义那么应该发出一个 undefined-function 类型的错误. (在尝试去写入它的定义时不会发出这样的错误.)
    
  • 也见(See Also):

    fboundp, fmakunbound, macro-function, special-operator-p
    
  • 注意(Notes):

    symbol-function 不能访问由 flet 或 labels 产生的词法函数名的值; 它只能访问全局函数值.
    
    当这个符号的函数定义不表示一个特殊操作符时, setf 可以和 symbol-function 一起使用来替换一个全局函数定义.
    
    (symbol-function symbol) ==  (fdefinition symbol)
    
    然而, fdefinition 接受的参数不仅仅是符号.
    

函数 SYMBOL-NAME

  • 语法(Syntax):

    symbol-name symbol => name
    
  • 参数和值(Arguments and Values):

    symbol---一个符号.
    name---一个字符串.
    
  • 描述(Description):

    symbol-name 返回符号 symbol 的名字. 如果名字 name 被修改那么后果是未定义的.
    
  • 示例(Examples):

    (symbol-name 'temp) =>  "TEMP"
    (symbol-name :start) =>  "START"
    (symbol-name (gensym)) =>  "G1234" ;for example
  • 副作用(Side Effects): None.

  • 受此影响(Affected By): None.

  • 异常情况(Exceptional Situations):

    如果 symbol 不是一个符号那么应该发出一个 type-error 类型的错误.
    
  • 也见(See Also): None.

  • 注意(Notes): None.

函数 SYMBOL-PACKAGE

  • 语法(Syntax):

    symbol-package symbol => contents
    
  • 参数和值(Arguments and Values):

    symbol---一个符号.
    contents---一个包对象或者 nil.
    
  • 描述(Description):

    返回这个符号 symbol 的 home 包.
    
  • 示例(Examples):

    (in-package "CL-USER") =>  #<PACKAGE "COMMON-LISP-USER">
    (symbol-package 'car) =>  #<PACKAGE "COMMON-LISP">
    (symbol-package 'bus) =>  #<PACKAGE "COMMON-LISP-USER">
    (symbol-package :optional) =>  #<PACKAGE "KEYWORD">
    ;; Gensyms are uninterned, so have no home package.
    (symbol-package (gensym)) =>  NIL
    (make-package 'pk1) =>  #<PACKAGE "PK1">
    (intern "SAMPLE1" "PK1") =>  PK1::SAMPLE1, NIL
    (export (find-symbol "SAMPLE1" "PK1") "PK1") =>  T
    (make-package 'pk2 :use '(pk1)) =>  #<PACKAGE "PK2">
    (find-symbol "SAMPLE1" "PK2") =>  PK1:SAMPLE1, :INHERITED
    (symbol-package 'pk1::sample1) =>  #<PACKAGE "PK1">
    (symbol-package 'pk2::sample1) =>  #<PACKAGE "PK1">
    (symbol-package 'pk1::sample2) =>  #<PACKAGE "PK1">
    (symbol-package 'pk2::sample2) =>  #<PACKAGE "PK2">
    ;; The next several forms create a scenario in which a symbol
    ;; is not really uninterned, but is "apparently uninterned",
    ;; and so SYMBOL-PACKAGE still returns NIL.
    (setq s3 'pk1::sample3) =>  PK1::SAMPLE3
    (import s3 'pk2) =>  T
    (unintern s3 'pk1) =>  T
    (symbol-package s3) =>  NIL
    (eq s3 'pk2::sample3) =>  T
  • 副作用(Side Effects): None.

  • 受此影响(Affected By):

    import, intern, unintern
    
  • 异常情况(Exceptional Situations):

    如果 symbol 不是一个符号那么应该发出一个 type-error 类型的错误.
    
  • 也见(See Also):

    intern
    
  • 注意(Notes): None.

访问器 SYMBOL-PLIST

  • 语法(Syntax):

    symbol-plist symbol => plist
    
    (setf (symbol-plist symbol) new-plist)
    
  • 参数和值(Arguments and Values):

    symbol---一个符号.
    plist, new-plist---一个属性列表.
    
  • 描述(Description):

    访问符号 symbol 的属性列表.
    
  • 示例(Examples):

    (setq sym (gensym)) =>  #:G9723
    (symbol-plist sym) =>  ()
    (setf (get sym 'prop1) 'val1) =>  VAL1
    (symbol-plist sym) =>  (PROP1 VAL1)
    (setf (get sym 'prop2) 'val2) =>  VAL2
    (symbol-plist sym) =>  (PROP2 VAL2 PROP1 VAL1)
    (setf (symbol-plist sym) (list 'prop3 'val3)) =>  (PROP3 VAL3)
    (symbol-plist sym) =>  (PROP3 VAL3)
  • 副作用(Side Effects): None.

  • 受此影响(Affected By): None.

  • 异常情况(Exceptional Situations):

    如果 symbol 不是一个符号那么应该发出一个 type-error 类型的错误.
    
  • 也见(See Also):

    get, remprop
    
  • 注意(Notes):

    应该避免使用 setf, 因为一个符号的属性列表是一个全局资源, 它可以包含在相同的 Lisp 镜像中由不相关的程序建立和依赖的信息.
    

访问器 SYMBOL-VALUE

  • 语法(Syntax):

    symbol-value symbol => value
    
    (setf (symbol-value symbol) new-value)
    
  • 参数和值(Arguments and Values):

    symbol---必须有一个值的符号.
    value, new-value---一个对象.
    
  • 描述(Description):

    访问这个符号 symbol 的值 cell.
    
  • 示例(Examples):

    (setf (symbol-value 'a) 1) =>  1
    (symbol-value 'a) =>  1
    ;; SYMBOL-VALUE cannot see lexical variables.
    (let ((a 2)) (symbol-value 'a)) =>  1
    (let ((a 2)) (setq a 3) (symbol-value 'a)) =>  1
    ;; SYMBOL-VALUE can see dynamic variables.
    (let ((a 2))
      (declare (special a))
      (symbol-value 'a)) =>  2
    (let ((a 2))
      (declare (special a))
      (setq a 3)
      (symbol-value 'a)) =>  3
    (let ((a 2))
      (setf (symbol-value 'a) 3)
      a) =>  2
    a =>  3
    (symbol-value 'a) =>  3
    (let ((a 4))
      (declare (special a))
      (let ((b (symbol-value 'a)))
        (setf (symbol-value 'a) 5)
        (values a b))) =>  5, 4
    a =>  3
    (symbol-value :any-keyword) =>  :ANY-KEYWORD
    (symbol-value 'nil) =>  NIL
    (symbol-value '()) =>  NIL
    ;; The precision of this next one is implementation-dependent.
    (symbol-value 'pi) =>  3.141592653589793d0  
  • 副作用(Side Effects): None.

  • 受此影响(Affected By):

    makunbound, set, setq
    
  • 异常情况(Exceptional Situations):

    如果 symbol 不是一个符号那么应该发出一个 type-error 类型的错误.
    
    如果符号 symbol 被解绑并且尝试去读取它的值那么应该发出 unbound-variable 类型的错误. (在尝试去写入它的值时不会发出这样的错误.)
    
  • 也见(See Also):

    boundp, makunbound, set, setq
    
  • 注意(Notes):

    symbol-value 可以被用于获取一个常变量的值. symbol-value 不能访问一个词法变量的值.
    

访问器 GET

  • 语法(Syntax):

    get symbol indicator &optional default => value
    
    (setf (get symbol indicator &optional default) new-value)
    
  • 参数和值(Arguments and Values):

    symbol---一个符号.
    indicator---一个对象.
    default---一个对象. 默认为 nil.
    value---如果表示的属性存在, 这个对象就是它的值; 否则, 就是指定的默认值 default.
    new-value---一个对象.
    
  • 描述(Description):

    get 在符号 symbol 的属性列表中找到一个属性指示符和指示符 indicator 一样的属性, 并且返回它对应的属性值. 如果这里有多个属性带有那个属性指示符, get 使用第一个这样的属性. 如果没有带有那个属性指示符的属性, 返回默认值 default.
    
    get 的 setf 可能被用于关联一个新对象和一个已存在那个符号 symbol 的属性列表中的指示符, 如果不存在就创建一个新的关联. 如果这里有多个属性带有那个属性指示符, get 的 setf 关联那个新值 new-value 到第一个这样的属性. 当一个 get 表达式形式被用作一个 setf 的 place 时, 任何提供的默认值 default 都根据正常从左到右的求值规则被求值, 但是它的值会被忽略.
    
  • 示例(Examples):

    (defun make-person (first-name last-name)
      (let ((person (gensym "PERSON")))
        (setf (get person 'first-name) first-name)
        (setf (get person 'last-name) last-name)
        person)) =>  MAKE-PERSON
    (defvar *john* (make-person "John" "Dow")) =>  *JOHN*
    *john* =>  #:PERSON4603
    (defvar *sally* (make-person "Sally" "Jones")) =>  *SALLY*
    (get *john* 'first-name) =>  "John"
    (get *sally* 'last-name) =>  "Jones"
    (defun marry (man woman married-name)
      (setf (get man 'wife) woman)
      (setf (get woman 'husband) man)
      (setf (get man 'last-name) married-name)
      (setf (get woman 'last-name) married-name)
      married-name) =>  MARRY
    (marry *john* *sally* "Dow-Jones") =>  "Dow-Jones"
    (get *john* 'last-name) =>  "Dow-Jones"
    (get (get *john* 'wife) 'first-name) =>  "Sally"
    (symbol-plist *john*)
    =>  (WIFE #:PERSON4604 LAST-NAME "Dow-Jones" FIRST-NAME "John")
    (defmacro age (person &optional (default ''thirty-something))
      `(get ,person 'age ,default)) =>  AGE
    (age *john*) =>  THIRTY-SOMETHING
    (age *john* 20) =>  20
    (setf (age *john*) 25) =>  25
    (age *john*) =>  25
    (age *john* 20) =>  25
  • 副作用(Side Effects): None.

  • 受此影响(Affected By): None.

  • 异常情况(Exceptional Situations):

    如果 symbol 不是一个符号那么应该发出一个 type-error 类型的错误.
    
  • 也见(See Also):

    getf, symbol-plist, remprop
    
  • 注意(Notes):

    (get x y) ==  (getf (symbol-plist x) y)
    
    在可移植的代码中不推荐数字和字符被用作指示符因为 get 使用 eq 来测试而不是使用 eql, 因此使用这样的指示符的影响是依赖于具体实现的.
    
    使用 get 没法去区分一个缺省的属性和值为默认值的属性. 但是, 见 get-properties.
    

函数 REMPROP

  • 语法(Syntax):

    remprop symbol indicator => generalized-boolean
    
  • 参数和值(Arguments and Values):

    symbol---一个符号.
    indicator---一个对象.
    generalized-boolean---一个广义 boolean.
    
  • 描述(Description):

    remprop 从符号 symbol 的属性列表中移除一个带有和指示符 indicator 一样属性指示符的属性. 如果这里有多个带有相同键的属性, remprop 只移除第一个这样的属性. 如果没有找到这样的属性那么 remprop 返回 false, 如果找到一个属性就返回 true.
    
    这个属性指示符和对应属性值通过破坏性地拼接这个属性列表以一种未定义的顺序被移除. 可允许的副作用相当于那些 remf 允许的, 如此这般:
    
    (remprop x y) ==  (remf (symbol-plist x) y)
    
  • 示例(Examples):

    (setq test (make-symbol "PSEUDO-PI")) =>  #:PSEUDO-PI
    (symbol-plist test) =>  ()
    (setf (get test 'constant) t) =>  T
    (setf (get test 'approximation) 3.14) =>  3.14
    (setf (get test 'error-range) 'noticeable) =>  NOTICEABLE
    (symbol-plist test)
    =>  (ERROR-RANGE NOTICEABLE APPROXIMATION 3.14 CONSTANT T)
    (setf (get test 'approximation) nil) =>  NIL
    (symbol-plist test)
    =>  (ERROR-RANGE NOTICEABLE APPROXIMATION NIL CONSTANT T)
    (get test 'approximation) =>  NIL
    (remprop test 'approximation) =>  true
    (get test 'approximation) =>  NIL
    (symbol-plist test)
    =>  (ERROR-RANGE NOTICEABLE CONSTANT T)
    (remprop test 'approximation) =>  NIL
    (symbol-plist test)
    =>  (ERROR-RANGE NOTICEABLE CONSTANT T)
    (remprop test 'error-range) =>  true
    (setf (get test 'approximation) 3) =>  3
    (symbol-plist test)
    =>  (APPROXIMATION 3 CONSTANT T)
  • 副作用(Side Effects):

    符号 symbol 的属性列表被修改.
    
  • 受此影响(Affected By): None.

  • 异常情况(Exceptional Situations):

    如果 symbol 不是一个符号那么应该发出一个 type-error 类型的错误.
    
  • 也见(See Also):

    remf, symbol-plist
    
  • 注意(Notes):

    在可移植的代码中不推荐数字和字符被用作指示符因为 remprop 使用 eq 来测试而不是 eql, 因此使用这样的指示符的影响是依赖于具体实现的. 当然, 如果你想要移除这样的属性, 你没有太多选择---考虑这个问题的时间是当你使用 get 的 setf 来建立这个属性的时候.
    

函数 BOUNDP

  • 语法(Syntax):

    boundp symbol => generalized-boolean
    
  • 参数和值(Arguments and Values):

    symbol---一个符号.
    generalized-boolean---一个广义 boolean.
    
  • 描述(Description):

    如果符号 symbol 被绑定就返回 true; 否则, 返回 false.
    
  • 示例(Examples):

    (setq x 1) =>  1
    (boundp 'x) =>  true
    (makunbound 'x) =>  X
    (boundp 'x) =>  false
    (let ((x 2)) (boundp 'x)) =>  false
    (let ((x 2)) (declare (special x)) (boundp 'x)) =>  true
  • 受此影响(Affected By): None.

  • 异常情况(Exceptional Situations):

    如果 symbol 不是一个符号那么应该发出一个 type-error 类型的错误.
    
  • 也见(See Also):

    set, setq, symbol-value, makunbound
    
  • 注意(Notes):

    函数 bound 只决定一个符号在全局环境中是否有一个值; 任何词法绑定都被忽略.
    

函数 MAKUNBOUND

  • 语法(Syntax):

    makunbound symbol => symbol
    
  • 参数和值(Arguments and Values):

    symbol---一个符号
    
  • 描述(Description):

    使这个符号 symbol 变为未绑定的, 不管之前它是否被绑定.
    
  • 示例(Examples):

    (setf (symbol-value 'a) 1)
    (boundp 'a) =>  true
    a =>  1
    (makunbound 'a) =>  A
    (boundp 'a) =>  false
  • 副作用(Side Effects):

    符号 symbol 的值 cell 会被求值.
    
  • 受此影响(Affected By): None.

  • 异常情况(Exceptional Situations):

    如果 symbol 不是一个符号那么应该发出一个 type-error 类型的错误.
    
  • 也见(See Also):

    boundp, fmakunbound
    
  • 注意(Notes): None.

函数 SET

  • 语法(Syntax):

    set symbol value => value
    
  • 参数和值(Arguments and Values):

    symbol---一个符号.
    value---一个对象.
    
  • 描述(Description):

    set 改变符号 symbol 的值 cell 的内容为给定的值 value.
    
    (set symbol value) ==  (setf (symbol-value symbol) value)
    
  • 示例(Examples):

    (setf (symbol-value 'n) 1) =>  1
    (set 'n 2) =>  2
    (symbol-value 'n) =>  2
    (let ((n 3))
      (declare (special n))
      (setq n (+ n 1))
      (setf (symbol-value 'n) (* n 10))
      (set 'n (+ (symbol-value 'n) n))
      n) =>  80
    n =>  2
    (let ((n 3))
      (setq n (+ n 1))
      (setf (symbol-value 'n) (* n 10))
      (set 'n (+ (symbol-value 'n) n))
      n) =>  4
    n =>  44
    (defvar *n* 2)
    (let ((*n* 3))
      (setq *n* (+ *n* 1))
      (setf (symbol-value '*n*) (* *n* 10))
      (set '*n* (+ (symbol-value '*n*) *n*))
      *n*) =>  80
      *n* =>  2
    (defvar *even-count* 0) =>  *EVEN-COUNT*
    (defvar *odd-count* 0) =>  *ODD-COUNT*
    (defun tally-list (list)
      (dolist (element list)
        (set (if (evenp element) '*even-count* '*odd-count*)
              (+ element (if (evenp element) *even-count* *odd-count*)))))
    (tally-list '(1 9 4 3 2 7)) =>  NIL
    *even-count* =>  6
    *odd-count* =>  20
  • 副作用(Side Effects):

    符号 symbol 的值被改变.
    
  • 受此影响(Affected By): None.

  • 异常情况(Exceptional Situations): None.

  • 也见(See Also):

    setq, progv, symbol-value
    
  • 注意(Notes):

    函数 set 已经被废弃.
    
    set 不能修改一个词法变量的值.
    

状况类型 UNBOUND-VARIABLE

  • 类优先级列表(Class Precedence List):

    unbound-variable, cell-error, error, serious-condition, condition, t
    
  • 描述(Description):

    类型 unbound-variable 由表示尝试去读取一个未绑定变量的值的错误状况组成.
    
    这个 cell (见 cell-error) 的值是这个未绑定变量的名字.
    
  • 也见(See Also):

    cell-error-name
    

猜你喜欢

转载自blog.csdn.net/zssrxt/article/details/80751394
10.