4

I accidentally unbound a built-in function (a subr) from its usual symbol. Is there a generic way to recover it?

Of course I could save my buffers and my session, exit Emacs and start another instance. That is, if the function I lost wasn't needed to save and exit. What can I do if I lose some really fundamental function such as write-region or get-buffer?

2
  • I'm not sure you can unbind functions defined in C code, did this actually happen to you, or is the question purely theoretical? If this was an ELisp function you could just reload the file where it is defined, well, guess you already knew that.
    – wvxvw
    Commented Sep 21, 2015 at 21:13
  • @wvxvw You can unbind almost any symbol. I think the only exceptions are nil and t. The built-in function still exists, of course, but if you unbind the symbol whose function slot is normally bound to it, how do you access it? And yes, I asked that because it happened to me, fortunately for a function that was easy to implement in a different way, but I wonder if there's a systematic way to recover. Commented Sep 21, 2015 at 21:25

1 Answer 1

1

After accidentally losing write-region (there's some weird interaction between flet and advice that I don't understand), I added this code early in my .emacs. I save all the subroutines in a separate obarray, so as long as I don't lose both fset and defalias I should be able to recover.

;; Before anything else, keep a copy of all built-in functions. This
;; is not used during normal operation, only when I accidentally
;; unbind a primitive, e.g. due to ill-advised advice.
;; https://emacs.stackexchange.com/questions/16806/recover-a-built-in-function-that-i-accidentally-unbound
(defvar subr-backup-obarray
  (let ((backup-obarray (make-vector (length obarray) 0)))
    (mapatoms (lambda (symbol)
                (if (and (fboundp symbol) (subrp (symbol-function symbol)))
                    (fset (intern (symbol-name symbol) backup-obarray)
                          (symbol-function symbol)))))
    backup-obarray)
  "Backup of all built-in functions.")
(defalias 'subr-backup
  ;; Why this strange definition? This way we get a byte-compiled
  ;; object that doesn't contain any call to a function symbol, only
  ;; bytecode opcodes and subr objects.
  (byte-compile
   (let ((intern-soft (list 'funcall (symbol-function 'intern-soft)))
         (symbol-function (list 'funcall (symbol-function 'symbol-function)))
         (symbol-name (list 'funcall (symbol-function 'symbol-name)))
         (symbolp (list 'funcall (symbol-function 'symbolp))))
     `(lambda (name)
        (,@symbol-function
         (,@intern-soft (if (,@symbolp name) (,@symbol-name name) name)
                        subr-backup-obarray)))))
  "Return the backup of the built-in function (subr) originally bound to NAME.
NAME may be a string or symbol.
If a symbol that is normally bound to a built-in function has become unbound
or bound to another function, the original subr binding can be restored with
  (fset 'SYMBOL (subr-backup 'SYMBOL))
or (if SYMBOL has no `defalias-fset-function' property)
  (defalias 'SYMBOL (subr-backup 'SYMBOL))")
1
  • Nice! (I wrote just about the same code while trying to answer your question, but did not have the time to clean it up and post it. :-) ) Commented Feb 15, 2016 at 18:20

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.