Bir dekoratör temelde sadece bir işlevdir .
Common Lisp Örneği:
(defun attributes (keywords function)
(loop for (key value) in keywords
do (setf (get function key) value))
function)
Yukarıda işlev bir sembol (tarafından döndürülecek DEFUN
) ve özellikleri sembolün özellik listesine koyduk .
Şimdi bunu bir fonksiyon tanımının etrafına yazabiliriz:
(attributes
'((version-added "2.2")
(author "Rainer Joswig"))
(defun foo (a b)
(+ a b))
)
Python'da olduğu gibi süslü bir sözdizimi eklemek istiyorsak, bir okuyucu makrosu yazarız . Bir okuyucu makrosu, s-ifade sözdizimi düzeyinde programlamamızı sağlar:
(set-macro-character
#\@
(lambda (stream char)
(let ((decorator (read stream))
(arg (read stream))
(form (read stream)))
`(,decorator ,arg ,form))))
Sonra yazabiliriz:
@attributes'((version-added "2.2")
(author "Rainer Joswig"))
(defun foo (a b)
(+ a b))
Lisp okuyucusu yukarıda şunları okur:
(ATTRIBUTES (QUOTE ((VERSION-ADDED "2.2")
(AUTHOR "Rainer Joswig")))
(DEFUN FOO (A B) (+ A B)))
Şimdi Common Lisp'te bir çeşit dekoratör var .
Makroları ve okuyucu makroları birleştirme.
Aslında bir işlevi değil, bir makro kullanarak gerçek kod yukarıdaki çeviri yapardı.
(defmacro defdecorator (decorator arg form)
`(progn
,form
(,decorator ,arg ',(second form))))
(set-macro-character
#\@
(lambda (stream char)
(declare (ignore char))
(let* ((decorator (read stream))
(arg (read stream))
(form (read stream)))
`(defdecorator ,decorator ,arg ,form))))
Aynı okuyucu makrosu ile kullanım yukarıdaki gibidir. Avantajı, Lisp derleyicisinin hala üst düzey form olarak görmesidir - * dosya derleyicisi üst düzey formlara özel davranır, örneğin derleme zamanı ortamına onlar hakkında bilgi ekler . Yukarıdaki örnekte, makronun kaynak koduna baktığını ve adı çıkardığını görebiliriz.
Lisp okuyucu yukarıdaki örneği şu şekilde okur:
(DEFDECORATOR ATTRIBUTES
(QUOTE ((VERSION-ADDED "2.2")
(AUTHOR "Rainer Joswig")))
(DEFUN FOO (A B) (+ A B)))
Hangi makro genişletilir alır:
(PROGN (DEFUN FOO (A B) (+ A B))
(ATTRIBUTES (QUOTE ((VERSION-ADDED "2.2")
(AUTHOR "Rainer Joswig")))
(QUOTE FOO)))
Makrolar okuyucu makrolardan çok farklıdır .
Makrolar kaynak kodunu geçirir, istediklerini yapabilir ve sonra kaynak kodunu döndürebilir. Giriş kaynağının geçerli Lisp kodu olması gerekmez. Herhangi bir şey olabilir ve tamamen farklı yazılabilir. Sonuç geçerli Lisp kodu olmalıdır. Ancak, oluşturulan kod da bir makro kullanıyorsa, makro çağrısında gömülü kodun sözdizimi yine farklı bir sözdizimi olabilir. Basit bir örnek: bir çeşit matematik sözdizimini kabul edecek bir matematik makrosu yazılabilir:
(math y = 3 x ^ 2 - 4 x + 3)
İfade y = 3 x ^ 2 - 4 x + 3
geçerli Lisp kodu değil, ancak makro örneğin ayrıştırıp geçerli Lisp kodunu şu şekilde döndürebilir:
(setq y (+ (* 3 (expt x 2))
(- (* 4 x))
3))
Lisp'te başka birçok makro kullanımı vardır.