The core point is that there is a difference between a function and a command.
In Emacs lisp, functions are not interactively callable by default. That means you can't access them via
M-x or bind them to a key or mouse click. If you want to do that, you need to explicitly declare the function to be
interactive, which you do by adding an
(interactive) form as the first line in the body (following the documentation string). An interactive function is called a command This is explained in the manual:
(info "(elisp) Using Interactive") (online version).
The error message you see,
Wrong type argument: commandp, my-function, is indicating that you're trying to call a function interactively, but that function isn't a command.
To explain the actual error, the letter
p is often used in lisp to indicate a predicate or test. In this case, Emacs is testing
my-function to see if it is a command using the test
commandp. It isn't, which leads to the error. Similar errors pop up whenever you use an object of the wrong type: if Emacs expects a string and you pass a symbol, you might see a reference to
stringp, for example.
To answer the question as asked, you need to add the
(interactive) line to the definition:
(defun my-function ()
(message "This is a great function"))
There are a lot of options for the
interactive form, supporting all kinds of ways of passing information to your function. Check the manual for all the details.
Keyboard macros are a special case in this context. A keyboard macro is a sequence of input events, represented as a string. Keyboard macros behave like commands, so you can bind them to keys without worrying about adding an
interactive declaration. For example, in the following:
(global-set-key (kbd "C-c l") "λ")
"λ" is a keyboard macro, so we can bind it to
C-c l without a problem. If we try to do the same thing with a function we have to be sure to define the function as
(global-set-key (kbd "C-c k")
(lambda () (insert "λ"))
;; C-c k is undefined! We tried to bind it to a function
(global-set-key (kbd "C-c m")
(lambda () (interactive) (insert "λ"))
;; C-c m is bound to a command that inserts λ