私はレキシカルバインディングを使用するように自分のコードを変換しようとしています。
ユーザがカスタマイズ可能なリスト( template-replace)からラムダ関数( replacer-inner
へのlet-bound)を呼び出す関数( format-template
マッチ文字列に基づいた関数の関数(-functions
)です。 replacer-inner関数は引数を取らずに文字列を返しますが、変数 foo
bar
および/または baz
は list
の引数の一部として format-template
に渡されます。
(setq lexical-binding t)
(defcustom template-replace-functions
'(("email"
(lambda() user-mail-address)
("apples"
(lambda ()
(cond ((= foo 1)
"one")
((= foo 2)
"two")
((= foo 3)
"three")
(t "four"))))
("bananas"
(lambda ()
(if (eq bar 'move)
"movement" "sit still")))))
"Association list of replacement functions.
For each STRING, the corresponding FUNCTION is called with no
arguments and must return a string."
:type '(repeat (group string function))
:group 'spice-girls)
(defun format-template (list)
(let* ((foo (nth 0 list))
(bar (nth 1 list))
(baz (nth 2 list))
template
(replacer-outer
(lambda ()
(replace-regexp-in-string
"\${\([^\s\t\n]*?\)}"
(lambda (match)
(let* ((key (match-string 1 match))
(replacer-inner
(cadr (assoc key template-replace-functions))))
(if (and replacer-inner
(stringp (funcall replacer-inner)))
(funcall replacer-inner) "")))
template t t))))
(setq template
...)
(if template (funcall replacer-outer))))
たとえば、 list
には bar
と baz
にレットバインドされた3つの要素が含まれています。 match-stringのキー
は、 template-replace-functions
の関数に関連する "bananas"
内部には:
(lambda ()
(if (eq bar 'move)
"movement" "sit still"))
この時点で、上記のラムダ関数は、動的バインディングを使っても問題ないが、字句バインディングを使ってうまくいくわけではない bar
を知る必要があります。
私の質問は、lambda関数が foo
bar
のlet-bound値から取る replacer-inner
baz
?
( replace-inner
を含む replace-outer
関数は、実際の関数の2つの場所のいずれかから呼び出されるため、何かを混乱させるだけです。私はここでインラインで書くことができたかもしれませんが、問題に追加する場合は、この方法でインクルードしました。)
編集:
途中で...
(setq lexical-binding t
foo 0
bar 0)
(setq inline-fun-1
'(lambda ()
(setq return
(if (eq foo 1)
"Pass" "Fail"))))
(defmacro lex-fun ()
`(let* ((foo 1)
(bar 1)
return)
(funcall ,inline-fun-1)))
(lex-fun) ; -> "Pass"
(defun inline-fun-2 ()
(setq return
(if (eq bar 1)
"Pass" "Fail")))
(defmacro lex-fun ()
`(let* ((foo 1)
(bar 1)
return)
(funcall ,inline-fun-2)))
(lex-fun) ; -> Lisp error: (void-variable inline-fun-2)
したがって、マクロ内のラムダ関数を拡張すると動作するように見えますが、名前付き関数ではありません。しかし、私はユーザーのラムダまたは名前付きの関数を許可したいです。これを回避するには?