コアポイントは、関数とコマンドに違いがあるということです。
Emacs lispでは、関数はデフォルトでは対話的に呼び出すことができません。つまりM-x、キーやマウスのクリックを介してアクセスしたり、バインドしたりすることはできません。それをしたい場合は、関数を明示的に宣言する必要がありますinteractive。これ(interactive)は、本文の最初の行として(ドキュメント文字列の後に)フォームを追加することによって行います。インタラクティブ機能はコマンドと呼ばれます。これはマニュアルで説明されています:((info "(elisp) Using Interactive") オンライン版)。
表示されるエラーメッセージWrong type argument: commandp, my-functionは、関数をインタラクティブに呼び出そうとしているが、その関数はコマンドではないことを示しています。
実際のエラーを説明するために、この文字pはしばしば述語またはテストを示すためにLispで使用されます。この場合、Emacsはmy-functiontestを使用したコマンドかどうかをテストしていcommandpます。そうではないため、エラーが発生します。間違ったタイプのオブジェクトを使用するたびに、同様のエラーがポップアップします。Emacsが文字列を予期していて、シンボルを渡すとstringp、たとえばへの参照が表示される場合があります。
質問に答えるには(interactive)、定義に次の行を追加する必要があります。
(defun my-function ()
(interactive)
(message "This is a great function"))
フォームには多くのオプションがありinteractive、関数に情報を渡すあらゆる種類の方法をサポートしています。詳細については、マニュアルを参照してください。
このコンテキストでは、キーボードマクロは特殊なケースです。キーボードマクロは、文字列として表される一連の入力イベントです。キーボードマクロはコマンドのように動作するため、interactive宣言を追加することを心配せずにキーボードマクロをキーにバインドできます。たとえば、次の場合:
(global-set-key (kbd "C-c l") "λ")
"λ"はキーボードマクロなのでC-c l、問題なくバインドできます。関数で同じことを行おうとする場合、関数を次のように定義する必要があります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 λ