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))")
nil
andt
. 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.