4

The situation I have is this. First, I run

(require 'prolog)

...which loads the system's default version of prolog.el, and makes the variable prolog-mode-version available. It has value "1.22".

Now, I know that my personal copy of this package, in /path/to/my/own/private/prolog.el, starts with

(defvar prolog-mode-version "1.25"
  "Prolog mode version number")

So I run

(load "/path/to/my/own/private/prolog.el")

...expecting that, after doing so, prolog-mode-version will now have value "1.25".

This is not what happens, though: according to describe-variable at least, the value of prolog-mode-version is still "1.22".


What must I need to do to (re-)load 'prolog from /path/to/my/own/private/prolog.el?

Drew
  • 75,699
  • 9
  • 109
  • 225
kjo
  • 3,145
  • 14
  • 42
  • 3
    `defvar`s (and `defcustom`s, which use `defvar`) can only be [defined once](https://www.gnu.org/software/emacs/manual/html_node/elisp/Defining-Variables.html). To re-evaluate a `defvar`, place point over it and `eval-defun` (`C-M-x`). – Tianxiang Xiong Feb 27 '17 at 17:22
  • @TianxiangXiong: thanks! How can I do what you describe programmatically? – kjo Feb 27 '17 at 17:23
  • 3
    Not easily. See: http://emacs.stackexchange.com/questions/2298/how-do-i-force-re-evaluation-of-a-defvar – Tianxiang Xiong Feb 27 '17 at 17:26
  • @TianxiangXiong: Thanks again. Come to think of it, I need to `eval` the whole file, since there's a ton of other `defvar`s in there... I never expected this to be such a nightmare... – kjo Feb 27 '17 at 17:31
  • If you're running your own version of the package, why not stop using the system-provided one? – Tianxiang Xiong Feb 27 '17 at 17:31
  • Why are you loading the built-in version of the package in the first place? – Tyler Feb 27 '17 at 17:31
  • @TianxiangXiong: I explain why here: http://emacs.stackexchange.com/q/31086/882 – kjo Feb 27 '17 at 17:34
  • @Tyler: see here http://emacs.stackexchange.com/q/31086/882 – kjo Feb 27 '17 at 17:35
  • Is there ever a situation where you have a personal version of the package installed but *don't* want to use it? It would be easier to check for the presence of your custom version, and load it if present, and if it isn't present *then* load the built-in. – Tyler Feb 27 '17 at 17:39
  • @Tyler: If the system version is more recent than my version, I'd prefer to use the system version. – kjo Feb 27 '17 at 17:48
  • Just use your local version. "Use system version if it's newer" sets you up for surprises--what if the system version breaks backward compatibility in some unexpected way? – Tianxiang Xiong Feb 27 '17 at 20:32

2 Answers2

7

You can unload the system prolog mode first, this unbinds all its variables, so that the new defvar init-forms will take effect:

(require 'prolog)
(when (version< prolog-mode-version "1.25")
  (unload-feature 'prolog)
  (load "/path/to/my/own/private/prolog.el"))

Note that unload-feature is not a commonly used function, so it's possible you may hit some bugs. Most packages are not written with unloading in mind. Glancing at prolog.el, I don't see anything that should be a problem though (examples of potentially "problematic" forms would be side-effecting top-level calls, apart from the usual defun, defvar, defconst, defcustom, etc).

npostavs
  • 9,033
  • 1
  • 21
  • 53
  • +1 for mentioning the caveat "*Most packages are not written with unloading in mind.*" – Drew Feb 27 '17 at 21:21
  • Thanks! I noticed that, although I had used `(require 'prolog)` in my original question, in your answer you used `(require 'prolog-mode)` instead. Was there a particular reason for that change? – kjo Mar 01 '17 at 12:18
  • 1
    @kjo no, that was a mistake on my part, fixed now. – npostavs Mar 01 '17 at 14:46
3

As an alternative to unload-feature, you could use this to check the version of the default package without actually loading the code:

(let ((version (with-temp-buffer
                 (insert-file (find-library-name "prolog"))
                 (re-search-forward "(defvar prolog-mode-version \"\\([^\"]+\\)")
                 (string-to-number (match-string 1)))))
  (if (< version 1.25)
      (load "/path/to/my/own/private/prolog.el")
    (require 'prolog)))
Tyler
  • 21,719
  • 1
  • 52
  • 92