Common lisp 有用性/功能点“;符号名称;?
乍一看,有一个函数返回一个符号的名称似乎有点愚蠢,必须使用该符号的名称来调用该函数。i、 e.在调用上下文中,函数将返回什么应该是显而易见的。另一方面,Common lisp 有用性/功能点“;符号名称;?,common-lisp,Common Lisp,乍一看,有一个函数返回一个符号的名称似乎有点愚蠢,必须使用该符号的名称来调用该函数。i、 e.在调用上下文中,函数将返回什么应该是显而易见的。另一方面,identity有时很有用(我忘了刚才在哪里了),但我认为(可能是错误的)符号功能的存在是有原因的,而不仅仅是作为一种身份 但是,该文件提供了一个可能的提示: (符号名'temp)=>“temp” (符号名称:开始)=>“开始” (符号名称(gensym))=>“G1234”;例如 我注意到:start意味着从关键字包中获取符号start的名称
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
类型的对象
符号是一种数据类型,具有多个单元格:
- 名称,一个字符串
- 可能是一个函数
- 可能是一个值
- 财产清单
- 可选择其实习所在的家庭套餐
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 = ?"))
###)))