Emacs Elisp:使用put/get代替defvar有什么缺点吗?

Emacs Elisp:使用put/get代替defvar有什么缺点吗?,emacs,elisp,Emacs,Elisp,我有一个移动到行尾的函数,但是 当已经在行的末尾时,返回到之前调用它的最后一个点 这需要将最后一个点的值存储在某个位置。 目前我正在将这一点存储在例如(defvar last point 1)中,但我认为 封装会更好(好吧,一致性可能会更好,因为它仍然 外部可见)使用(将“我的移动结束行”放在最后一点1) 和(获取“我的移动行尾”最后一点) 这样做有什么缺点?属性比普通变量慢。此外,它们也较少使用和使用 因此,可能阅读您的代码的人不太理解您的代码 如果您想明确您的变量是一个内部变量,那么 用双破

我有一个移动到行尾的函数,但是 当已经在行的末尾时,返回到之前调用它的最后一个点

这需要将最后一个点的值存储在某个位置。 目前我正在将这一点存储在例如
(defvar last point 1)
中,但我认为 封装会更好(好吧,一致性可能会更好,因为它仍然 外部可见)使用
(将“我的移动结束行”放在最后一点1)
(获取“我的移动行尾”最后一点)


这样做有什么缺点?

属性比普通变量慢。此外,它们也较少使用和使用 因此,可能阅读您的代码的人不太理解您的代码

如果您想明确您的变量是一个内部变量,那么 用双破折号来命名是一种惯例 `最后一点

还可以尝试在函数和变量的名称上添加前缀 不与Emacs中使用的名称冲突

最后,使用属性的主要问题是它们不是 buffer local,但您的变量应该在示例中:

(defvar my--last-point ())
(make-variable-buffer-local 'my--last-point)

(defun my-last-point ()
   (interactive)
   (if (and my--last-point (eolp))
       (go to my--last-point and set it to nil))
     (go to the end of line and set my--last-point))
这样,您的函数将不会使用中一个缓冲区的点值
另一个。

用作变量的符号在其变量槽中只取一个值,但启用了一个属性列表,您可以在其中存储多个值


属性列表可用于将多个质量链接到单个符号上。

对于此任务,变量更清晰。当您存储特定于该符号的信息时(如使用“disable”属性禁用命令),应该使用symbol属性,但这里的情况并非如此。

我不太确定您的断言是否会导致该属性变慢
get
将在symbol plist上使用一个循环,在我的例子中,这个循环只有10个元素长,而
symbol value
将执行一系列重定向检查。如果新属性被推到plist的头部而不是尾部,
get
可能比
symbol value
更快。在我的例子中,
put
/
get
的主要优点是函数变成了一个原子:它不关心任何外部变量。我可以移动它/重命名它/随便什么。我不必考虑这个函数所依赖的一个额外变量。@abo abo变量查找不涉及调用
符号值
,就像属性访问不涉及调用
符号plist
。相反,这两种操作都是基本操作,都有自己的操作码(
varref
get
)。因此,它们的性能可能是相同的,尽管属性列表查找通常具有复杂性
O(n)
,而变量查找是固定时间的。@abo abo abo我不确定您是否可以在任何地方阅读此内容。我认为字节编译器的内部没有文档记录。但是,您可以阅读字节编译器源代码(在
bytecomp.el
和friends中),也可以反汇编表单。例如,尝试
(反汇编(byte compile sexp(lambda()user full name)))
(反汇编(byte compile sexp(lambda()(get user full name'standard value)))
谢谢,我会看看您提到的内容。但是,字节码必须映射到C源代码,对吗?我看到
get
有效地使用了
symbol-plist
@abo-abo,但它是C语言中的函数调用,比Emacs-Lisp中的函数调用快得多。这是相对缓慢的。因此,
(get'user full name'标准值)
(plist get(symbol plist'user full name)标准值)
快得多,即使这两种形式在语义上是等效的。前者是一个单基元C操作,而后者在Emacs Lisp中涉及两个昂贵的函数调用。但是此信息是特定于此符号的,因为没有其他函数使用它。@abo abo不,它不是。它不是特定符号的特定和固有属性,而是恰好由符号的函数定义使用的数据。因此,符号属性在语义上是错误的位置。符号属性不是动态数据存储。那就是,嗯……变量:)我的C++-ish/JavaScript-ish直觉告诉我,这个的语义没有问题。正如我从Emacs C代码中看到的,实现这个过程不是太慢。“abo abo ER,嗯,C++和javascript不是精确的Emacs LISP,所以你的直觉可能不是这里最好的向导。使用一个变量,真的。符号属性不是数据存储。它们不像C++中的对象属性,而是更像修饰语(例如,代码>公共< /代码>,<代码>私有< /代码>,<代码> const 等)。您知道,符号属性是全局的,不是吗?是否确实要全局存储上一个点?对我来说,一个缓冲区局部变量似乎更合适。是的,我在问题中提到过它,它对这种情况并不重要。我正在寻找除此之外的其他缺点。在emacs帮助列表上问这个问题。那里有真正的emacs大师,看看他们对这个问题的看法会很有趣:abo abo:我认为你应该使用一个不同的例子?任何存储点都需要缓冲区本地,在这种情况下,
put
/
get
显然是不合适的。我知道你已经对此发表了评论,但这仍然是人们在阅读你的问题时首先会注意到的事情。