3

I have a function that moves to the end of line, but when already at end of line, moves back to the last point where it was called before.

This requires the value of that last point to be stored somewhere. Currently I'm storing this point in e.g (defvar last-point 1), but I think it would be better for encapsulation (well, consistency maybe since it will still be visible to the outside) to use (put 'my-move-end-of-line 'last-point 1) and (get 'my-move-end-of-line 'last-point).

Any disadvantages to doing this?

abo-abo
  • 20,038
  • 3
  • 50
  • 71
  • You are aware that, symbol properties are global, aren't you? Are you sure that you want to store the previous point globally? To me, a buffer-local variable seems to be more appropriate. –  Feb 20 '14 at 14:51
  • Yes, I kind of mentioned it in the question and it doesn't matter for this case. I'm looking for other disadvantages besides that one. – abo-abo Feb 20 '14 at 14:56
  • Ask this question on the emacs-help list. There are real emacs gurus there and it would be interesting to see what they think about this problem: http://news.gmane.org/gmane.emacs.help – Tom Feb 20 '14 at 16:22
  • abo-abo: I think you should use a different example? Anything storing *point* pretty much needs to be buffer-local, in which case `put`/`get` is clearly inappropriate. I know you've already commented on that, but it's still the first thing that people are going to notice when they read your question. – phils Feb 20 '14 at 21:20

3 Answers3

2

A variable is clearer for this task. A symbol property should be used when you store information specfic to that symbol (like using the 'disable property to disable a command) which is not really the case here.

Tom
  • 7,515
  • 7
  • 38
  • 54
  • But this info *is* specific to this symbol as no other function does/should use it. – abo-abo Feb 20 '14 at 14:40
  • 2
    @abo-abo No, it's not. It's not a *specific* and *inherent* property of that *specific* symbol, but rather *data* that just happens to be used by the symbol's function definition. As such, a symbol property is the *wrong* place semantically. Symbol properties are not dynamic data store. That's, well… variables :) –  Feb 20 '14 at 14:54
  • Well my C++-ish / JavaScript-ish intuition tells there's nothing wrong with the semantics of this. And as I see from Emacs C code, the implementation for this isn't too slow. – abo-abo Feb 20 '14 at 14:58
  • @abo-abo Er, well, C++ and Javascript aren't exactly Emacs Lisp, so your intuition is probably not the best guide here. Use a variable, really. Symbol properties are not data storage. They are not like object attributes in C++, but more like modifiers (e.g. `public`, `private`, `const`, etc.). –  Feb 20 '14 at 15:58
1

Property are slower than plain variable. Also they are less used and so less understood by those who might read your code.

If you want to make clear that your variable is an internal one, there is a convention to name it with a double-dash like `my--last-point'.

Try also to put some prefix on the name of your function and variable to not have collision with name used in Emacs.

Lastly, the main problem with using property is that they are not buffer local, but your variable should be in you example:

(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))

Like that, your function won't use point value from one buffer in another.

Rémi
  • 8,172
  • 2
  • 27
  • 32
  • I'm not so sure on your assertion that they're slower. `get` will use a loop on symbol plist which is only 10 elements long in my case, while `symbol-value` will do bunch of checking for redirection. If new properties were pushed to the head of plist instead of tail, `get` would probably be faster than `symbol-value`. The main advantage to `put` / `get` in my case is that the function becomes an atom: it doesn't care about any external variables. I can move it / rename it / whatever. I don't have to think about that one extra variable that this function depends on. – abo-abo Feb 20 '14 at 11:24
  • @abo-abo Variable lookup doesn't involve a call to `symbol-value`, just like property access doesn't involve a call to `symbol-plist`. Rather, both are *primitive* operations, with their own opscodes (`varref` and `get`). As such, their performance is probably equal, though property list lookup generally has complexity `O(n)`, whereas variable lookup is constant time. –  Feb 20 '14 at 17:48
  • @abo-abo I'm not sure whether you can actually *read* this anywhere. I don't think that the internals of the byte compiler are documented. However, you can read the byte compiler source (in `bytecomp.el` and friends), and you can disassemble forms. For instance, try `(disassemble (byte-compile-sexp (lambda () user-full-name)))` or `(disassemble (byte-compile-sexp (lambda () (get user-full-name 'standard-value))))` –  Feb 20 '14 at 17:53
  • Thanks, I'll have a look at the things you mentioned. But still, the bytecodes have to map to to C source, right? I see that `get` effectively uses `symbol-plist`. – abo-abo Feb 20 '14 at 18:07
  • @abo-abo But it's a function call in *C*, which is by far faster than a function call in Emacs Lisp. These are relatively slow. As such, `(get 'user-full-name 'standard-value)` is much faster than `(plist-get (symbol-plist 'user-full-name) 'standard-value)`, even though both forms are semantically equivalent. The former is a single primitive C operation, whereas the latter involves two expensive function calls in Emacs Lisp. –  Feb 20 '14 at 18:48
0

A symbol used as variable takes just one value in its variable-slot, but enables a property list, where you can store a multitude of values.

Properties list are useful to link several qualities onto a single symbol.

Andreas Röhler
  • 4,804
  • 14
  • 18