What's a defconst and why you should use it05 Jan 2015, by Artur Malabarba.
Any Emacs package developer worth their salt knows the difference between a
defcustom. These two comprise the vast majority of variable
definitions in Elisp code, but there's a third child, the
regular variables and customizable variables only really differ when it comes to
customize system, constants differ in loading logic in a subtle but
defvar is evaluated, the value specified is assigned to the variable
only if the previous value was void (if the variable wasn't defined yet).
defconst, on the other hand, always sets the symbol's value to
the (new) given value. This becomes most relevant when a package is upgraded
after having been loaded in Emacs. Any variables defined by the package will
retain their old values until Emacs is restarted, whereas constants will be
updated to their new values.
In a sense, somewhat ironically, Elisp constants are the least constant of all variables. Rest assured though, they were given this name for a reason. This behaviour is indeed suited for storing values that should be constant. Here's a simple use-case which arose for us in sx.el.
The StackExchange API requires that we provide filters to specify which information we want to receive. Of course, we were storing these filters in variables and then using that information while printing the question.
The problem with this approach would only be seen after an upgrade. Lets say we decide to also display a question's score. Without a doubt, we'd change the above to something like this.
Now the user upgrades
sx.el, tries to run it again, and gets hit on the face
with an error!
sx-browse-filter is still using the old value, so the question score is not
returned by the API. That means
.score is nil and
number-to-string throws an
error. Changing the
defconst was all we needed to prevent this
If you're wondering why you've never run into such an issue, that's because
package.el used to have another bug, which would never load new package
versions upon upgrade. That has been fixed in 25.1—packages are now reloaded
on upgrade—so you should ensure your package won't run into new problems by
making proper use of constants.
Simply put, you should
defconst whenever there are functions or macros in a
package which rely on the variable having that specific value (kind of like a
proper constant). This way you'll know you never have old values hanging around.