Kısa cevap vermek için, Ortak Lisp veya Etki Alanına Özel Diller (DSL) için dil sözdizimi uzantılarını tanımlamak için makrolar kullanılır. Bu diller mevcut Lisp kodunun içine yerleştirilmiştir. Şimdi, DSL'lerin Lisp'e benzeyen bir sözdizimi (Peter Norvig'in Ortak Lisp için Prolog Tercümanı gibi ) veya tamamen farklı olabilir (örn . Clojure için Infix Notation Math ).
İşte daha somut bir örnek:
Python, dilde yerleşik liste anlayışlarına sahiptir. Bu, genel bir durum için basit bir sözdizimi sağlar. Çizgi
divisibleByTwo = [x for x in range(10) if x % 2 == 0]
0 ile 9 arasındaki tüm çift sayıları içeren bir liste verir. Python'da 1,5 gün içinde böyle bir sözdizimi yoktu; bunun gibi bir şey kullanırsınız:
divisibleByTwo = []
for x in range( 10 ):
if x % 2 == 0:
divisibleByTwo.append( x )
Bunların her ikisi de işlevsel olarak eşdeğerdir. Güvensizliği askıya almamızı isteyelim ve Lisp'in sadece yineleme yapan ve liste kavrayışlarının eşdeğerini yapmanın kolay bir yolu olmayan çok sınırlı bir döngü makrosuna sahip olduğunu varsayalım.
Lisp'de aşağıdakileri yazabilirsiniz. Bu örnek, Lisp kodunun iyi bir örneği değil Python koduyla özdeş olarak seçilmiştir.
;; the following two functions just make equivalent of Python's range function
;; you can safely ignore them unless you are running this code
(defun range-helper (x)
(if (= x 0)
(list x)
(cons x (range-helper (- x 1)))))
(defun range (x)
(reverse (range-helper (- x 1))))
;; equivalent to the python example:
;; define a variable
(defvar divisibleByTwo nil)
;; loop from 0 upto and including 9
(loop for x in (range 10)
;; test for divisibility by two
if (= (mod x 2) 0)
;; append to the list
do (setq divisibleByTwo (append divisibleByTwo (list x))))
Daha ileri gitmeden önce, bir makronun ne olduğunu daha iyi açıklamalıyım. Kod üzerinde koda göre yapılan bir dönüşümdür . Yani, yorumlayıcı (veya derleyici) tarafından okunan ve bir argüman olarak kodu alan bir kod parçası, manipüle eder ve sonucu döndürür ve daha sonra yerinde çalıştırılır.
Tabii ki bu çok fazla yazım ve programcılar tembel. Böylece DSL'yi liste kavrayışı yapmak için tanımlayabiliriz. Aslında, zaten bir makro kullanıyoruz (döngü makrosu).
Lisp birkaç özel sözdizimi formu tanımlar. '
Tırnak işareti ( ), bir sonraki belirtecin değişmez olduğunu belirtir. Quasiquote veya backtick ( `
), bir sonraki belirtecin kaçan bir değişmez olduğunu gösterir. Kaçışlar virgül operatörü tarafından belirtilir. Gerçek '(1 2 3)
Python's eşdeğerdir [1, 2, 3]
. Başka bir değişkene atayabilir veya yerinde kullanabilirsiniz. Aklınıza gelebilecek `(1 2 ,x)
Python eşdeğer olarak [1, 2, x]
nerede x
değişken önceden tanımlanır. Bu liste gösterimi, makrolara giren büyünün bir parçasıdır. İkinci bölüm, akıllıca kod yerine makroları değiştiren Lisp okuyucusudur, ancak en iyi aşağıda gösterilmiştir:
Böylece, lcomp
(listeyi anlama kısaltması) adlı bir makro tanımlayabiliriz . Sözdizimi tam olarak örnekte kullandığımız python gibi olacak [x for x in range(10) if x % 2 == 0]
-(lcomp x for x in (range 10) if (= (% x 2) 0))
(defmacro lcomp (expression for var in list conditional conditional-test)
;; create a unique variable name for the result
(let ((result (gensym)))
;; the arguments are really code so we can substitute them
;; store nil in the unique variable name generated above
`(let ((,result nil))
;; var is a variable name
;; list is the list literal we are suppose to iterate over
(loop for ,var in ,list
;; conditional is if or unless
;; conditional-test is (= (mod x 2) 0) in our examples
,conditional ,conditional-test
;; and this is the action from the earlier lisp example
;; result = result + [x] in python
do (setq ,result (append ,result (list ,expression))))
;; return the result
,result)))
Şimdi komut satırında çalışabiliriz:
CL-USER> (lcomp x for x in (range 10) if (= (mod x 2) 0))
(0 2 4 6 8)
Çok temiz, ha? Şimdi burada bitmiyor. İsterseniz bir mekanizmanız veya bir boya fırçanız var. İstediğiniz herhangi bir sözdizimine sahip olabilirsiniz. Python veya C # with
sözdizimi gibi. Veya .NET'in LINQ sözdizimi. Sonunda, insanları Lisp'e çeken şey budur - nihai esneklik.