EDIT : Son Emacs bunu yapmanın daha iyi bir yolu , bağımsız değişkenlerin sayısını denetlemek için bir derleyici makro tanımlamaktır . Normal bir makro kullanarak orijinal yanıtım aşağıda korunur, ancak bir derleyici makrosu üstündür, çünkü işlevin çalışma zamanında funcall
veya apply
çalışma zamanında geçmesini engellemez .
Emacs'ın son sürümlerinde, işleviniz için bağımsız değişken sayısını kontrol eden ve eşleşmezse bir uyarı (hatta hata) üreten bir derleyici makro tanımlayarak bunu yapabilirsiniz. Tek incelik, derleyici makrosunun orijinal işlev çağrı formunu değerlendirme veya derleme için değiştirmeden geri göndermesidir. Bu bir &whole
argüman kullanarak ve değerini döndürerek yapılır . Bu şu şekilde yapılabilir:
(require 'cl-lib)
(defun my-caller (&rest args)
(while args
(message "%S %S" (pop args) (pop args))))
(define-compiler-macro my-caller (&whole form &rest args)
(when (not (cl-evenp (length args)))
(byte-compile-warn "`my-caller' requires an even number of arguments"))
form)
(my-caller 1 2 3 4)
(my-caller 1 2)
(funcall #'my-caller 1 2 3 4) ; ok
(apply #'my-caller '(1 2)) ; also ok
(my-caller 1) ; produces a warning
(funcall #'my-caller 1 2 3) ; no warning!
(apply #'my-caller '(1 2 3)) ; also no warning
Not funcall
ve apply
derleyici tarafından makro argüman denetimi baypas şimdi kullanılabilir, ancak bunlar. Adlarının rağmen, derleyici makrolar da yoluyla değerlendirilmesi 'yorumlanır' sırasında genişletilmiş gibi görünüyor C-xC-e, M-xeval-buffer, sen değerlendirirken yanı sıra bu örneği derleme hataları alacak böylece.
Orijinal cevap aşağıdaki gibidir:
Jordon'un "genişletme zamanında uyarı sağlayacak bir makro kullanma" önerisini şu şekilde uygulayabilirsiniz. Çok kolay olduğu ortaya çıktı:
(require 'cl-lib)
(defmacro my-caller (&rest args)
(if (cl-evenp (length args))
`(my-caller--function ,@args)
(error "Function `my-caller' requires an even number of arguments")))
(defun my-caller--function (&rest args)
;; function body goes here
args)
(my-caller 1 2 3 4)
(my-caller 1 2 3)
Yukarıdakileri bir dosyada derlemeye çalışmak .elc
, derleme günlüğünde tıklanabilir bir hata mesajı vererek başarısız olur (hiçbir dosya üretilmez):
test.el:14:1:Error: `my-caller' requires an even number of arguments
Derleme işleminin devam etmesine izin vererek bir hata yerine uyarı üretmek için (error …)
ile de değiştirebilirsiniz (byte-compile-warn …)
. (Bunu yorumlarda belirttiği için Jordon'a teşekkürler).
Makrolar derleme zamanında genişletildiğinden, bu kontrolle ilişkili çalışma zamanı cezası yoktur. Tabii ki, başkalarının my-caller--function
doğrudan aramasını durduramazsınız , ancak en azından çift tire kuralını kullanarak "özel" bir işlev olarak tanıtabilirsiniz.
Dikkate değer bir dezavantaj bu amaçla bir makro kullanmanın yani my-caller
artık birinci sınıf bir fonksiyonudur: Eğer bunu geçemez funcall
veya apply
çalışma zamanında (ya da en azından bunu beklemek ne olmaz). Bu bakımdan, bu çözüm, gerçek bir işlev için derleyici uyarısı bildirmek kadar iyi değildir. Tabii ki, kullanmak apply
zaten derleme zamanında işleve geçirilen argümanların sayısını kontrol etmeyi imkansız hale getirecektir, bu yüzden bu belki de kabul edilebilir bir değiş tokuştur.