Я не проверял это, но почему бы не написать макрос для инкапсуляции того, что вы хотите? Может быть, что-то вроде следующего?
(defmacro one-shot-hook (name hook &rest body)
`(defun ,name ()
(remove-hook ',hook ',name)
,@body)
Тогда, например
(macroexpand-all-1
'(one-shot-hook test c-mode-hook
(message "Yay!")))
дает
(defun test nil
(remove-hook (quote c-mode-hook) (quote test))
(message "Yay!"))
(когда я его переформатировал).
Это устраняет проблему необходимости знать имя функции, в которой вы находитесь, что в любом случае потребовало бы неприятной макрологии (я не уверен, возможно ли это).
Еще одна вещь, я бы, вероятно, предложил просто установить сначала переменную flag, равную nil, чтобы ваш код тестировал, чтобы решить, следует ли запускать. Тогда вам не нужно все время возиться с добавлением и удалением хуков: результат, вероятно, будет гораздо проще настроить и понять для всех, кто использует ваш код.