字句バインディングを使用したlet内のDefunは、「関数が定義されていることが不明です」というバイトコンパイル警告を表示します。


13

defun内部でlet字句バインディングを使用してクロージャーを作成することにより、静的変数の効果を取得したい。ただし、ファイルをバイトコンパイルすると、警告が表示されます。私は何か間違ったことをしていますか、そうでない場合、この警告を抑制する方法はありますか?

MCVEを作成しました:

;; -*- lexical-binding: t -*-

(let ((count 0))
  (defun increase-count ()
    (interactive)
    (setq count (1+ count))
    (message "Count is: %d" count))

  ;; The warning happens here.
  (increase-count))

コードは期待どおりに機能します。関数increase-countは「Count is:n」を出力します。nは呼び出されるたびに増加します。ただし、このファイルをバイトコンパイルすると、次の警告が表示されます。

In end of data:
mcve.el:11:1:Warning: the function ‘increase-count’ is not known to be
    defined.

increase-countletブロックの最後に呼び出される前に、常に定義する必要があるように思えます。そうではありませんか?


defun考えていることを行わず、常に最上位の定義を作成します。エリスプは結局のところスキームではない
...-wasamasa

2
トップレベルの定義が作成されることは承知しています。それが私が欲しいものです。トップレベルの定義をクロージャにしたいだけです。このバイトコンパイルの警告を除いて、私が望むように動作しているようです。
ウィルクンケル

回答:


7

関数を定義するかどうかを決定するバイトコンパイラの方法は非常に「単純」で、「明らかな」場合でもだまされます。しかし、コンパイラに何が起こるかを理解させる方法でそれを書くことができます:

(defalias 'increase-count
  (let ((count 0))
    (lambda ()
      (interactive)
      (setq count (1+ count))
      (message "Count is: %d" count))))

もちろん、バイトコンパイラのロジックを改善することをお勧めします。パッチは歓迎します。


5

バイトコンパイラの警告を抑制するには、コードの前に、列0(左端)から開始してこれを追加してみてください。

(declare-function increase-count "your-file-name.el")

C-h f declare-function あなたに言う:

declare-functionはのLispマクロですsubr.el

(declare-function FN FILE &optional ARGLIST FILEONLY)

関数FNが定義されていることをバイトコンパイラに伝えますFILEFILE引数はバイトコンパイラによって、しかしによって使用されていない check-declareファイルには、の定義が含まれていることを確認したパッケージ、FN

FILELispファイル(この場合、".el" 拡張子はオプション)またはCファイルのいずれかです。Cファイルは、Emacs "src/"ディレクトリを基準にして展開されます。Lispファイルはを使用して検索されlocate-library、それが失敗した場合、宣言を含むファイルの場所に対して相対的に展開されます。プレフィックスFILE付きのA "ext:"は外部ファイルです。 check-declareそのようなファイルが見つかった場合はチェックし、見つからない場合はエラーなしでスキップします。

オプションARGLIST指定FNの引数であるか、またはt指定しないこと FNの引数を。省略ARGLISTデフォルトtではなく、nilnil ARGLIST空の引数リストを指定し、明示的にはt ARGLIST、後に引数を与えることができますプレースホルダです。

オプションのFILEONLYnon- nilは、check-declareFILE定義することではなく、存在するもののみをチェックすることを意味しますFN。これはcheck-declare、たとえば、を認識しない関数定義を対象としていdefstructます。

のためにcheck-declare、このステートメントは行の最初の非空白でなければならないことに注意してください。

詳細については、情報ノードを参照してください(elisp)Declaring Functions


当面FILEONLYのケースには非ゼロの引数が必要ですか?ところで、私は同じ答えを与えていただろう;-)。
トビアス

@Tobias:FILEONLY私にとっては、ここでは必要ないようでした。これはcheck-declarefおよびgdefuns を認識することを示すように思われます。
ドリュー

@Drew、私は約その最後のコメントを考えるfと、g唯一のコンテキストで理にかなってemacs.stackexchange.com/q/39439
phils

@phils:はい、私はこれを言うつもりでした:FILEONLY私にとっては、ここでは必要ないようでした。これはdefun をcheck-declare認識することを示すように思われますincrease-count。;-)
ドリュー

3

問題の定義を内部に配置するeval-and-compileことも、ステファンの正解と同じ結果を表面的に達成すると信じています

(eval-and-compile
  (let ((count 0))
    (defun increase-count ()
      (interactive)
      (setq count (1+ count))
      (message "Count is: %d" count))))

しかし、私は使用の微妙さにほとんど精通してeval-and-compileおらず、さらに、このアプローチが何らかの形で優れているとは期待していません。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.