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
  • 77,472
  • 10
  • 114
  • 243
kjo
  • 3,247
  • 17
  • 48
  • 3
    defvars (and defcustoms, which use defvar) can only be defined once. 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 defvars 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,203
  • 1
  • 24
  • 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
  • 22,234
  • 1
  • 54
  • 94