2011-09-16 17 views
0

より効果的な方法でプロジェクトディレクトリにアクセスするために使用できる一連の関数を生成できるマクロを作成しようとしています。次のマクロを見ると、自分がやろうとしていることを知っているはずです。閉鎖を扱うelisp

(defmacro create-project-cmd (project-name project-dir &optional subdir-list) 
    (if (null subdir-list) 
     `(fset (intern ,project-name) #'(lambda() (interactive) (dired ,project-dir))) 
     `(dolist (dir ,subdir-list) 
     (fset (intern (concat ,project-name "-" dir)) 
       #'(lambda() (interactive) (dired (concat ,project-dir "/" dir))))))) 

ここでの問題は、最後の行に「DIR」はdolist句の「DIR」に結合することになっています。そして、elispにクロージャがないので、生成された関数を呼び出すと、dirが無効であると不平を言うでしょう。

コードからわかるように、私は "project-dir"のクロージャを偽造しています。私は "dir"と同じ方法でそれを偽造することはできません。レキシカルレットはここではうまく動作しますが、記憶に問題があるので避けようとしています。それを使用する習慣を育てたくない(おそらく私はあまりにも甘いかもしれません)。

私はこれを処理する良い方法がありません。誰でも良い提案がありますか?

+0

の可能重複[克服する方法Emacs Lisp閉鎖のためのローカル変数の欠如](http://stackoverflow.com/questions/6955544/how-to-overローカル変数for-emacs-lisp-closure)があります。 – phils

答えて

2

編集:字句-LETが出ている場合は、どのようにこのようなものについて:

(defmacro create-project-cmd (project-name project-dir &optional subdir-list) 
    (if (null subdir-list) 
     `(fset (intern ,project-name) #'(lambda() (interactive) (dired ,project-dir))) 
    (let ((fsets nil)) 
     (dolist (dir subdir-list) 
     (add-to-list 
     'fsets 
     `(fset (intern (concat ,project-name "-" ,dir)) 
       #'(lambda() (interactive) (dired (concat ,project-dir "/" ,dir)))))) 
     `(progn ,@fsets)))) 

(create-project-cmd "projfoo" "projdir" ("foo" "bar" "baz")) 

(symbol-function 'projfoo-bar) 
(lambda nil (interactive) (dired (concat "projdir" "/" "bar"))) 
+0

あなたの情報をありがとうございますが、私はそのすべてを考慮しました。コードからわかるように、私はすでに "project-dir"のマクロを使ってクロージャーを偽造しています。しかし、 "dir"では、マクロの中にあるので、別のマクロ呼び出しを使用すると値の代わりにシンボル名だけが渡され、実行時まで値を取得できません。試して失敗しました。私はまた、レキシカルレットの使用を避けようとしています。メモリの問題は結果になる必要があるので、私はそれを使用する習慣を育てたくはありません。 – sudo

+0

はい、私は本当に 'lexical-let'をそこで使いたいと思っていました。これはどう? ^^ – phils

+0

ああ、私はそんなことを考えていましたが、@演算子を完全に忘れました。どうもありがとう。 :) – sudo