Common lisp 有用性/功能点“;符号名称;?

Common lisp 有用性/功能点“;符号名称;?,common-lisp,Common Lisp,乍一看,有一个函数返回一个符号的名称似乎有点愚蠢,必须使用该符号的名称来调用该函数。i、 e.在调用上下文中,函数将返回什么应该是显而易见的。另一方面,identity有时很有用(我忘了刚才在哪里了),但我认为(可能是错误的)符号功能的存在是有原因的,而不仅仅是作为一种身份 但是,该文件提供了一个可能的提示: (符号名'temp)=>“temp” (符号名称:开始)=>“开始” (符号名称(gensym))=>“G1234”;例如 我注意到:start意味着从关键字包中获取符号start的名称

乍一看,有一个函数返回一个符号的名称似乎有点愚蠢,必须使用该符号的名称来调用该函数。i、 e.在调用上下文中,函数将返回什么应该是显而易见的。另一方面,
identity
有时很有用(我忘了刚才在哪里了),但我认为(可能是错误的)符号功能的存在是有原因的,而不仅仅是作为一种身份

但是,该文件提供了一个可能的提示:

(符号名'temp)=>“temp”
(符号名称:开始)=>“开始”
(符号名称(gensym))=>“G1234”;例如
我注意到
:start
意味着从关键字包中获取符号
start
的名称,其中关键字包仅由
表示。 (
:关键字
为其较长形式,无需使用)。因此,在这种情况下,
symbol name
只起到删除包前缀的作用

它可能做的另一件事是,如果实现不区分大小写,它将通过删除提供的符号名称中的大小写来获得实际名称

这大概就是我所缺少的功能,还是它有什么重要性

我对符号感到困惑的一件事(现在澄清)是
symbol plist
并没有告诉您关于符号的一切(比如,它是否包含特殊变量或函数的值)。相反,plist主要是一个遗留特性,现在基本上被哈希表所取代。因此,调用
symbol plist
将返回
NIL
,即使在符号上设置了特殊变量


最后一个问题,Paul Graham在第8章(第133页)中说,“你可以将符号用作数据对象和事物的名称,而不了解两者之间的关系”。如果我们现在很少使用plists,那么今天,我们通常根本不使用符号“作为数据对象”,而是使用符号作为事物的名称(当然,所有这些都与CL中的二元性有关,即,
符号函数
符号值
).

处理符号名称并不是那么愚蠢。例如,当您构建预处理器时—您读取一些数据,将其转换为列表结构,然后一些代码正在处理这些列表,并在
符号名称
为时触发一些附加逻辑,比如说
取消我的ubermacro
。这正是格雷厄姆的名言——你将符号视为数据


而且(在我看来)如果不使用plist,通常不使用符号作为数据,这是不正确的。plist只在许多地方有用。宏所做的很多工作是将符号作为数据/名称进行处理。

符号是对象。您可以创建它们并通过编程方式传递它们。这些对象的属性之一是它们的名称,它是一个字符串
Symbol name
是该代码的读取器(而不是访问器)。就这些

符号也用于表示代码。在本例中,它们由读取器创建,并由编译器使用。然而,这并不是它们的唯一用途,规范也没有做出这样的假设。我希望这能解决你问题的核心

下面是一个函数,给定一个符号,该函数返回位于同一个包中但名称相反的符号:

(defun reverse-symbol (symbol)
  (intern (make-symbol (reverse (symbol-name symbol)))
          (symbol-package symbol)))
下面是一个函数,给定一个字符串指示符,它返回指定的字符串:

(defun designated-string (string-designator)
  (ctypecase string-designator
    (string string-designator)
    (symbol (symbol-name string-designator))))
您还可以在宏和编译器宏中执行各种各样的诡计,方法是检查给定形式的符号名称并应用一些约定(您不应该…)

乍一看,有一个函数返回一个符号的名称似乎有点愚蠢,必须使用该符号的名称来调用该函数

那是错误的<代码>符号名称是用符号而不是名称调用的。它以字符串形式返回名称

我注意到:start意味着从关键字包中获取符号start的名称,其中关键字包简单地表示为:。(:关键字为其较长形式,不需要使用)。因此,在这种情况下,符号名只起到删除包前缀的作用

否,
symbol name
以字符串形式返回符号的名称。关键字符号是
symbol
类型的对象

符号是一种数据类型,具有多个单元格:

  • 名称,一个字符串
  • 可能是一个函数
  • 可能是一个值
  • 财产清单
  • 可选择其实习所在的家庭套餐
不要使用符号“作为数据对象”,而是作为事物的名称

不,作为数据对象的符号有很多用途。例如,Lisp源代码使用许多符号。但它也可以出现在各种数据中

CL-USER 6 > 'foo
FOO

CL-USER 7 > (type-of 'foo)
SYMBOL

CL-USER 8 > (symbol-name 'foo)
"FOO"

CL-USER 9 > (type-of (symbol-name 'foo))
SIMPLE-BASE-STRING

CL-USER 10 > (mapcar #'symbol-name '(a b c defun foo bar))
("A" "B" "C" "DEFUN" "FOO" "BAR")

CL-USER 11 > (mapcar #'type-of *)
(SIMPLE-BASE-STRING SIMPLE-BASE-STRING SIMPLE-BASE-STRING SIMPLE-BASE-STRING SIMPLE-BASE-STRING SIMPLE-BASE-STRING)

让我们假设您想编写一些协议,用于通过某个串行通道在两个不同系统之间传输结构位

(defgeneric transmit-object (o stream))
符号的方法是什么

(defmethod transmit-object ((o symbol) stream)
  ... (symbol-name o) ...)
特别是,在需要对符号进行推理时,您肯定不知道符号的名称,如果不使用
symbol name
(或者一些绝对骇人听闻的黑客,比如将符号打印到字符串并使用该字符串),您就无法编写这样的协议

关于
symbol plist
,实现完全可以自由地在符号的属性列表上保留各种信息。我甚至不确定是否不允许实现(更聪明的版本):


这可能是不允许的,但我不确定。当然,函数定义以这种方式保存曾经是相当常见的。

既然您还没有接受答案,下面是我的看法

对于大多数日常编程符号,因此对于符号名称, 它们不是很有用。大多数情况下,它们是用于他们的 独特性。无论它们如何闪耀
(defun symbol-value (s)
  (let* ((d (load-time-value (cons nil nil)))
         (v (get s secret-value-indicator d)))
    (when (eq v d)
      (error ...))
    v))
(loop for i in list collect i)
(loop :for i :in list :collect i)
(loop #:for i #:in list #:collect i)
(defbean peer ()
  (id)
  (next
   beats))
(defclass peer nil
  ((id :initarg :id :reader peer-id)
   (next :initarg :next :accessor peer-next)
   (beats :initarg :beats :accessor peer-beats)))
(defsqlite-table artists
  (id :auto-key)
  (artist-name :t)
  (sort-artist-name :t :n))
(progn
 (defparameter +create-artists-sql+
   "CREATE TABLE artists (
  id INTEGER PRIMARY KEY NOT NULL,
   artist_name TEXT NOT NULL,
   sort_artist_name TEXT
)")
 (defun create-artists-table (pjs-sqlite::db pjs-sqlite::recursive log)
   ###)
 (eval-when (:load-toplevel)
   ###)
 (defun insert-artists
        (pjs-sqlite::db artist-name sort-artist-name &key (id nil id-p))
   ###)
 (defun update-artists
        (pjs-sqlite::db id
         &key (artist-name nil artist-name-p)
         (sort-artist-name nil sort-artist-name-p))
   ###)
 (defun delete-artists (pjs-sqlite::db id)
   (with-sqlite-statements (pjs-sqlite::db
                            (pjs-sqlite::stmt
                             "DELETE FROM artists WHERE id = ?"))
     ###)))