Kodumu sözcüksel bağlama kullanmaya çevirmeye çalışıyorum.
Kullanıcı-özelleştirilebilir bir listeden bir lambda işlevini ( replaceer-iç
'e bağlı) çağıran bir işlevim ( format-template
) var ( template-replace Bir eşleme dizgisine dayalı işlevlerin işlevleri
). Değiştirici iç işlevi hiçbir argüman almaz ve bir dizge döndürür, ancak foo
bar
ve/veya değişkenlerini kullanması gerekebilir olabilir listesinin
argümanının bir parçası olarak format-template
'e aktarılan baz
.
(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))))
Örneğin, list
, foo
bar
ve baz
'a bağlı üç öğeyi içerir. Eşleme dizesinin tuşu
"bananas"
olup template-replace-functions
öğesinde bir işleve bağlanır ve replace- değerini ayarlar. iç
için:
(lambda ()
(if (eq bar 'move)
"movement" "sit still"))
Bu noktada, yukarıdaki lambda işlevinin, dinamik bağlamayı kullanarak, ancak sözcüksel bağlamayı kullanarak çok iyi olmayan bar
'ı bilmesi gerekir.
Sorum şu; yerine replace-iç
olan lambda işlevinin foo
bar
değerine bağlı olmasını sağlamak için bunu nasıl yaparım? ve baz
?
(Sadece bir şeyi karıştırmak için replace-internal
içeren replace-outer
fonksiyonu, gerçek fonksiyondaki iki yerden birinden çağrıldığı için izinlidir. Buraya satır içi yazabilirdim, ancak problemi eklediğinde bu şekilde dahil ettim.)
Düzenle:
Yarı yolda ...
(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)
Yani, bir makro içindeki lambda işlevini genişletmek işe yarayabilir, ancak adlandırılmış bir işlev değil. Ama kullanıcı lambda veya adlandırılmış işlevlere izin vermek istiyorum. Bu konuda nasıl geçilir?