Svante在另一个答案中通过显示字符串指示符来引起我的注意:
(string= :& "&") -> T
看看CLHS,他们说A designator is an object that denotes another object.
这很好,但由于这些是不同的对象,某种强制需要在某处发生。我的意思是,如果下面的列表指示符可以被'非零原子'满足,那么某些逻辑就存在于处理它的地方。
列表指示符对象列表的指示符;也就是说 表示列表的对象,它是以下之一:非零原子 (表示单元素列表,其元素是非零原子)或a 正确的清单(表示自己)。
我认为指示符可能是一个概念,例如,通用函数......但是来自CLHS的以下行......
除非另有说明,否则在表示对象的情况下 可能会被多次使用,它是依赖于实现的 对象仅被强制一次或是否每次都发生强制 必须使用对象的时间。
......然后看起来非常具体。
所以我的问题
干杯
答案 0 :(得分:6)
指示符不再是(或更少)指定另一个对象的对象。关于他们的语言并没有什么特别之处;指示符的概念只是使某些编程实践更容易的概念。词汇表说:
designator n。表示另一个对象的对象。在里面 如果参数被描述为a,则为运算符的字典条目 一个类型的指示符,操作符的描述写在一个 假设对该类型的适当强制已经存在的方式 发生了;也就是说,该参数已经是所表示的类型。 有关更多详细信息,请参阅Section 1.4.1.5 (Designators)。
该部分的链接很有帮助:
1.4.1.5 Designators
指示符是表示另一个对象的对象。
当操作符的参数被描述为指示符时, 运算符的描述以假定的方式编写 参数的值是表示的对象;那就是那个 参数已经是表示的类型。 (具体的性质) 由“«type»指示符”或“指示符”表示的对象 «type»“可在”«type»指示符的词汇表条目中找到。“)
能够在词汇表中查找内容有助于。例如,字符串指示符可以代表字符串:
string designator n。字符串的指示符;也就是说 表示字符串的对象,它是以下之一:字符(表示 一个以字符作为唯一元素的单例字符串,a symbol(表示其名称的字符串)或字符串(表示 本身)。意图是该术语与行为一致 串;扩展字符串的实现必须扩展含义 这个术语的兼容方式。
该标准也恰好定义了函数string,该函数获取字符串指示符指定的字符串:
返回x描述的字符串;具体是:
- 如果x是字符串,则返回。
- 如果x是符号,则返回其名称。
- 如果x是一个字符,则返回包含该字符的字符串。 string可能会执行额外的,实现定义的 转换。
这简化了必须使用字符串和字符串之类的函数的实现。例如,您可以定义 make-person 函数接受字符串指示符:
(defun make-person (name)
"Return a person with the name designated by NAME."
(list :name (string name)))
(defun person-name (person)
"Return the name of a person (a string)."
(getf person :name))
指定符的概念不仅仅是一种编程约定,它使得定义灵活的API变得更容易。 Common Lisp被定义为将一堆现有Lisp联合起来的语言,它可能是统一不同实现行为的更简单方法之一。
在case
中使用了列表指示符的概念list designator n。对象列表的指示符;那是, 一个表示列表的对象,它是以下之一:非零原子 (表示单元素列表,其元素是非零原子)或a 正确的清单(表示自己)。
case keyform {normal-clause} * [otherwise-clause] =>结果*
normal-clause :: =(keys form *)
keys - 对象列表的指示符。在案件的情况下, 符号t和否则不能用作键指示符。至 这些符号本身称为键,指示符(t)和 (否则)必须分别使用。
我不知道返回列表指示符指定的列表的函数,但是编写起来很容易(这不会处理 t 和的特殊行为 案例需要,但它一般处理列表指示符:
(defun to-list (x)
"Return the list designated by x."
(if (listp x) x
(list x)))
这些约定有时候会对你自己的代码有用,特别是如果你定义的东西是“注册表”的东西。例如,如果你写了以下任何一个:
(defmacro deftransform (name &rest args)
`(setf (gethash ',name *transforms*)
(make-transform ,@args)))
(defmacro deftransform (name &rest args)
(setf (get ',name 'transform) (make-transform ,@args)))
然后,您可以将变换指示符的概念定义为变换对象或符号(指定*变换*表中符号的值,或符号上变换属性的值)。 E.g:
(defun transform (x)
(if (transformp x) x
(gethash name *transforms*)))
(defun transform (x)
(if (transformp x) x
(get x 'transform)))
这可能会使您的部分代码更易于使用。功能指示符类似
答案 1 :(得分:3)
对象的指示符是不必然是对象,但对象可以推断。任何对象都可以轻易指定自己。
例如,character
不 a(a的子类型)string
,但character
可以有时而不是string
,因为它表示一个字符串。
实现以不同的方式做事,查看各自的源代码。 您可以找到类似下面的使用级代码或类似
的内容(defun human-address (human)
(etypecase human
(human ...)
(string (human-address (gethash human *humanity*)))))
甚至
(defun human-address (human)
(when (stringp human)
(setq human (gethash human *humanity*)))
(unless (human-p human)
(error ...))
...)
如果由于引导问题而导致defgeneric
尚未提供,或者作为优化而被避免。
系统级指示符不是用户可扩展的。 即,你不能定义你自己的包或字符串指示符。
但是,您可以为自己的类型定义自己的指示符,例如:
(defclass human ...)
(defvar *humanity* (make-hash-table ...))
(defgeneric human-address (human)
(:method ((human human))
...)
(:method ((name string))
(human-address (gethash name *humanity*))))
此处string
充当human
的指示符。
答案 2 :(得分:2)
对象指示符通常包含多种对象来表示或命名目标对象。
好的指示符定义不包括nil
(即你被允许不指定一个对象),具有不相交的指示符类型,而指示符通常是一个名称指向预期对象的对象或对象。
注意:在我看来,指示符是不必要的快捷方式,在使用REPL或原型设计时非常有用。
以下是主观分类指示符的非详尽列表。
好的指示符(基本上,非零,命名或容器,指示符):
不太好的指示符:
external file format designator
它的定义是故意开放式和依赖于实现的,所以由实现来尝试定义好的指示符。除此之外,没关系。
它的定义基于字符串指示符。除此之外,没关系。
我对此感到好奇,主要是因为流不是可靠的路径名指示符。只有文件流和这些流的同义词流是。
对于可以接受流或自己打开流的给定函数,有时将已经打开的流传递给读取或写入并且可选地保持打开是有用的,有时传递要在其中使用的路径名是有用的。 with-open-file
(或类似的),所以这里的汇合就会丢失。
但是,这样的函数应该分为两部分,一部分明确地采用流指示符,另一部分明确地采用路径名指示符。
字符串包含一个字符,而不是相反。但是,单个字符串可以用它的单个字符命名,所以我想这不是太糟糕。
这个指示符不好的一个特殊情况是破坏性操作,它只接受实际字符串。这是预期的,但这是您必须注意的细节,例如如果您从string-upcase
切换到nstring-upcase
。
错误的指示符:
您必须知道(nil)
没有指定者。
nil
代表标准可读表,您不能不指定可读表。或者,不显眼的nil
不会发出错误信号。
nil
用作上下文相关的指示符,在这种情况下,您不能不指定流。或者,不显眼的nil
不会发出错误信号。
与流指示符相同的原因。