SORU
6 Kasım 2008, PERŞEMBE


Lisp makroları bu kadar özel yapan nedir

Programlama dilleri Paul Graham'ın denemeler bir okuma lisp makroları gitmek için tek yol olduğunu düşünüyorum. Yoğun bir geliştirici diğer platformlarda çalışan olarak, lisp makroları kullanma ayrıcalığına sahip oldum. Buzz anlamak isteyen birisi olarak, bu özellik çok güçlü kılan açıklayınız.

Lütfen aynı zamanda dünyanın python, java, c#, c kalkınma anlarım bir şey için bu ilişki.

CEVAP
7 Ocak 2011, Cuma


Kısa cevap: dil tanımlamak için kullanılır Common Lisp veya Etki alanı Belirli bir Dil (Dolaylı olarak) uzantısı sözdizimi makrolar. Bu dilleri doğru mevcut Lisp kodu içinde gömülü. Şimdi, Dolaylı olarak Lisp Peter Norvig Prolog Interpreter Ortak Lisp gibi () sözdizimi benzer ya da tamamen farklı (Clojure örneğin Infix Notation Math) olabilir.

Daha somut bir örnek olarak: Python liste üreteçleri yerleşik bir dili vardır. Bu iki ile bölünebilir divisibleByTwo = [x for x in range(10) if x % 2 == 0] 9 0 numaralarını verir ortak bir dava için basit bir sözdizimi sağlar. Python 1.5 günlerde bu tür sözdizimi vardı, ve o ifade var:

divisibleByTwo = []
for x in range( 10 ):
   if x % 2 == 0:
      divisibleByTwo.append( x )

Bu fonksiyonel olarak eşdeğerdir. Bu güvensizlik ve Lisp gibi bizim süspansiyon çağırmak izin var sadece yineleme ve liste üreteçleri eşdeğer yapmak için kolay bir yolu yok bu çok sınırlı bir döngü bir makro.

Lisp aşağıdaki yazabilirsiniz. Bu yapmacık örnek Lisp iyi bir örnek değil Python kodu için aynı olması için çekilen dikkat etmelisiniz.

;; 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))))

Ben daha önce: makro nedir biraz açıklayayım. Kod kod kod dönüştürme. Bu kod parçası bir argüman bir manipülasyon yaptığı gibi kod alan yorumlayıcı (veya derleyici) tarafından okunan ve döner yerde çalıştırılan sonucudur.

Tabii ki yazarak bir sürü var ve programcılar tembel. Liste üreteçleri yapmak için DSL tanımlayabiliriz. Aslında, biz zaten bir Makro (Makro döngü) kullanarak.

Lisp özel sözdizimi çift tanımlar. Alıntı (') bir sonraki token bir edebi olduğunu gösterir. Quasiquote veya backtick (`) bir sonraki token kaçar ile bir değişmez olduğunu gösterir. Kaçar virgül operatörü ile gösterilir. Literal '(1 2 3) Python [1, 2, 3] eşdeğerdir. Yerine başka bir değişken ya da kullanmak için atayabilirsiniz. X bir değişkendir Python ` eşdeğer olarak(1 2 ,x) [1, 2, x] önceden tanımlanmış düşünebilirsiniz. Bu liste gösterim makrolar gider büyünün bir parçası. İkinci bölüm kodu için dokunulmaz ama en aşağıda gösterildiği Lisp okuyucu

Bir makro lcomp () liste üreteci kısaltılmışı tanımlayabiliriz. Sözdizimi tam olarak örnekte [x for x in range(10) if x % 2 == 0] - (lcomp x for x in (range 10) if (= (% x 2) 0)) kullandığımız python gibi olacak

(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
            ;; conditioanl-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 uygulayabiliriz:

CL-USER> (lcomp x for x in (range 10) if (= (mod x 2) 0))
(0 2 4 6 8)

Çok güzel, değil mi? Şimdi bu kadarla da bitmiyor. Bir mekanizma - bir boya fırçası var. Muhtemelen herhangi bir sözdizimi vardır. Ya da C gibi Python#'In sözdizimi ile. Ya .NET SERİ sözdizimi. Sonunda, bu insanlar Lisp için çekiyor ne esneklik.

Bunu Paylaş:
  • Google+
  • E-Posta
Etiketler:

YORUMLAR

SPONSOR VİDEO

Rastgele Yazarlar

  • Grace Su

    Grace Su

    6 Ocak 2006
  • MikeyMacintosh

    MikeyM

    28 Aralık 2009
  • ShoSho

    ShoSho

    20 Ocak 2010