16

I wrote a function, and I want to call it via M-x, and bind it to a key. This is my function:

(defun my-function ()
    (message "This is a great function"))

If I try to call it with M-x my-function, I get the error: [no match] in the mini-buffer.

If I try to bind it to a key (or mouse click):

(global-set-key (kbd "C-c a") 'my-function)

It appears to work, but when I try to call it with C-c a, I get the error

Wrong type argument: commandp, my-function

Why can't I use my function?

7
  • 5
    I volunteer this question as a generic response to frequently asked questions on this subject. Feel free to expand or clarify however makes sense to make the question and answer discoverable by & useful to people with similar problems!
    – Tyler
    Commented Oct 16, 2018 at 13:54
  • 1
    Thanks for doing this, Tyler. I flagged the Q for a moderator to please convert this to a community question.
    – Drew
    Commented Oct 16, 2018 at 14:46
  • One thing I wonder about is whether the title should just quote the error message. That might be easier for people to find, and it might allow for answers that do not have to do with just adding interactive - e.g., sometimes a command disappears from a new version of a library. The error can be raised in any context where Emacs expects a command.
    – Drew
    Commented Oct 16, 2018 at 14:48
  • It would be good if folks now searched the wiki for, say, commandp, to try to find other Qs that can be closed as duplicates of this one. Be careful to read the Q&A, though, as some are different. In some cases, the answer (and the Q context) might be worth repeating here. In other cases the question is unrelated and should be left as is (not closed).
    – Drew
    Commented Oct 16, 2018 at 14:51
  • 1
    @Drew I wasn't sure how best to 'advertise' this in the title. The commandp error only pops up with keybindings, so people running into this from the M-x direction won't see the connection. Not sure what the best balance is between a clear, concise title and a title that will pop up for all the relevant search queries. Feel free to tweak as you like!
    – Tyler
    Commented Oct 16, 2018 at 15:04

1 Answer 1

27

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 ()
    (interactive)
    (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 interactive:

(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 λ
3
  • one suggestion I'd like to add, make it clear that you need to do C-x C-e before doing M-x my-function in your example. Also as an emacs beginner I'm really not 100% clear yet on what exactly C-x C-e does or when you need to run it, but it appears that uh... when you run it, it parses the buffer and overwrites my-function in memory because if I don't run C-x C-e M-x runs the function from the last time I ran C-x C-e
    – jrh
    Commented Oct 21, 2018 at 18:31
  • It would appear that C-x C-e evaluates the buffer, it seems that the result of evaluating a buffer containing a defun is registering the function, though this article seems to make me think that it should just run the function, and yet the only thing shown in the minibuffer is my-function (implying it returns the function?), not This is a great function. I must be missing something here.
    – jrh
    Commented Oct 21, 2018 at 18:44
  • 1
    Thanks for your comments, @jrh. This question & answer are addressing a particular aspect of elisp, how to make a function interactive (i.e., turn function into a command). You're asking about more fundamental aspects of elisp, and are beyond the scope of this question. I recommend working through the the Emacs Lisp Intro. You seem to be confused about the difference between evaluating a function definition, which (re-)defines a function but doesn't actually call it, and calling the function, which runs the function code.
    – Tyler
    Commented Oct 22, 2018 at 15:12

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.