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 funcallveya 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 &wholeargü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 funcallve applyderleyici 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--functiondoğ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-callerartık birinci sınıf bir fonksiyonudur: Eğer bunu geçemez funcallveya 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 applyzaten 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.