
Έχω διαβάσει πολλά που LISP να επαναπροσδιορίσει τη σύνταξη on the fly, προφανώς με μακροεντολές. Είμαι περίεργος πόσο κάνει αυτό πραγματικά να πάμε; Μπορείτε να επαναπροσδιορίσει τη δομή της γλώσσας τόσο πολύ ώστε να γίνει οριακά ένας μεταγλωττιστής για άλλη γλώσσα; Για παράδειγμα, θα μπορούσατε να αλλάξετε τη λειτουργική φύση της LISP σε μια πιο προσανατολισμένη αντικείμενο τη σύνταξη και τη σημασιολογία, ίσως να πω με το συντακτικό πιο κοντά σε κάτι σαν Ruby;


Ιδιαίτερα, είναι δυνατόν να απαλλαγούμε από την κόλαση παρένθεση χρησιμοποιώντας μακροεντολές; Έχω μάθει αρκετά (Emacs-) LISP για να προσαρμόσετε το Emacs με τη δική μου μικρο-χαρακτηριστικά, αλλά είμαι πολύ περίεργος πόσο μακριά μακροεντολές μπορεί να πάει στην προσαρμογή της γλώσσας.

 
Πόσο μακριά μπορεί να πάει μακροεντολές LISP;
=============================================



Αυτή είναι μια πολύ καλή ερώτηση.


Νομίζω ότι είναι λεπτή, αλλά σίγουρα λογοδοτούν:


Οι μακροεντολές που δεν έχουν κολλήσει σε s-εκφράσεις. Δείτε το μακρο LOOP για μια πολύ πολύπλοκη γλώσσα γραμμένο με λέξεις-κλειδιά (σύμβολα). Έτσι, ενώ μπορεί να ξεκινήσει και να τελειώσει το βρόχο με παρενθέσεις, μέσα σε αυτό έχει τη δική του σύνταξη.


Παράδειγμα:



```
(loop for x from 0 below 100
      when (even x)
      collect x)

```

Τούτου λεχθέντος, πιο απλό μακροεντολές χρησιμοποιούν μόνο s-εκφράσεις. Και θέλετε να «κολλήσει» με τη χρήση τους.


Αλλά s-εκφράσεις, όπως Sergio έχει απαντήσει, αρχίζουν να αισθάνονται δεξιά. Η σύνταξη παίρνει έξω από το δρόμο και να ξεκινήσετε την κωδικοποίηση στο δέντρο σύνταξη.


Όσο για μακροεντολές αναγνώστη, ναι, θα μπορούσε ενδεχομένως να γράψετε κάτι σαν αυτό:



```
#R{
      ruby.code.goes.here
  }

```

Αλλά τότε θα πρέπει να γράψετε τη δική σας Ruby σύνταξη αναλυτή.


Μπορείτε, επίσης, να μιμούνται μερικές από τις Ruby κατασκευάζει, όπως τετράγωνα, με μακροεντολές που συγκεντρώνει τις υπάρχουσες Lisp κατασκευές.



```
#B(some lisp (code goes here))

```

θα μεταφραστεί σε



```
(lambda () (some lisp (code goes here)))

```

Δείτε [αυτή τη σελίδα](http://rottcodd.wordpress.com/2007/11/29/lambda-shortcut/) για το πώς να το κάνουμε.

 

Ναι, μπορείτε να επαναπροσδιορίσουμε τη σύνταξη, έτσι ώστε Lisp γίνεται compiler. Μπορείτε να το κάνετε αυτό χρησιμοποιώντας «Αναγνώστης μακροεντολές,» που είναι διαφορετικό από το κανονικό «Compiler μακροεντολές» που είστε πιθανώς σκέψης του.


Common Lisp έχει την ενσωματωμένη δυνατότητα να ορίσετε νέα σύνταξη για τις μακροεντολές αναγνώστη και του αναγνώστη για την επεξεργασία των εν λόγω σύνταξη. Αυτή η επεξεργασία γίνεται σε ανάγνωση του χρόνου (που έρχεται πριν από την κατάρτιση ή eval χρόνο). Για να μάθετε περισσότερα σχετικά με τον ορισμό μακροεντολές αναγνώστη στην Common Lisp, δείτε το Common Lisp Hyperspec - θα θέλετε να διαβάσετε [Χρ. 2, «Σύνταξη»](http://www.lispworks.com/documentation/HyperSpec/Body/02_.htm) και [Χρ. 23, "Reader"](http://www.lispworks.com/documentation/HyperSpec/Body/23_.htm) . (Πιστεύω Σχέδιο έχει την ίδια δυνατότητα, αλλά δεν είμαι τόσο εξοικειωμένοι με αυτό - δείτε τις [πηγές Σχέδιο](http://arclanguage.org/install) για τη [γλώσσα προγραμματισμού Arc](http://arclanguage.org) ).


Ως ένα απλό παράδειγμα, ας υποθέσουμε ότι θέλετε Lisp να χρησιμοποιήσετε άγκιστρα και όχι παρενθέσεις. Αυτό απαιτεί κάτι σαν τους ακόλουθους ορισμούς αναγνώστη:



```
;; { and } become list delimiters, along with ( and ).
(set-syntax-from-char #\{ #\( )
(defun lcurly-brace-reader (stream inchar) ; this was way too easy to do.
  (declare (ignore inchar))
  (read-delimited-list #\} stream t))
(set-macro-character #\{ #'lcurly-brace-reader)

(set-macro-character #\} (get-macro-character #\) ))
(set-syntax-from-char #\} #\) )

;; un-lisp -- make parens meaningless
(set-syntax-from-char #\) #\] ) ; ( and ) become normal braces
(set-syntax-from-char #\( #\[ )

```

Είσαι λέγοντας Lisp ότι η {είναι σαν ένα (και το} είναι σαν ένα). Στη συνέχεια, μπορείτε να δημιουργήσετε μια συνάρτηση ( `lcurly-brace-reader`) ότι ο αναγνώστης θα καλέσει κάθε φορά που βλέπει ένα {, και μπορείτε να χρησιμοποιήσετε `set-macro-character`για να ορίσετε τη λειτουργία αυτή στην {. Στη συνέχεια, να σας πω Lisp ότι (και) είναι σαν [και] (δηλαδή, δεν έχει νόημα σύνταξη).


Άλλα πράγματα που θα μπορούσατε να κάνετε περιλαμβάνουν, για παράδειγμα, [τη δημιουργία ενός νέου σύνταξη κορδόνι](http://www.weitz.de/cl-interpol/) ή με τη χρήση [και] να επισυνάψουν συμβολισμό σε αποτύπωση και επεξεργασία του σε S-εκφράσεις.


Μπορείτε επίσης να πάτε πέρα από αυτό, επαναπροσδιορίζει το σύνολο της σύνταξης με τις δικές σας μακρο χαρακτήρες που θα προκαλέσει δράσεις στον αναγνώστη, έτσι ώστε ο ουρανός είναι πραγματικά το όριο. Αυτό είναι μόνο ένας από τους λόγους για τους οποίους [ο Paul Graham](http://www.paulgraham.com/icad.html) και [άλλοι](http://gigamonkeys.com/book/introduction-why-lisp.html) συνεχίζουν λέγοντας ότι Lisp είναι μια καλή γλώσσα για να γράψει ένα compiler.

 

Δεν είμαι ειδικός Lisp, καλό δεν είμαι καν Lisp προγραμματιστής, αλλά μετά από λίγο πειραματίζεται με τη γλώσσα μου κατέληξα στο συμπέρασμα ότι μετά από λίγο η παρένθεση αρχίσει να γίνει «αόρατο» και θα αρχίσετε να βλέπετε τον κώδικα ως θέλετε να είναι. Θα αρχίσουν να πληρώνουν μεγαλύτερη προσοχή στις συντακτικές δομές που δημιουργούν μέσω s-exprs και μακροεντολές, και λιγότερο με το λεξιλογικό μορφή του κειμένου των καταλόγων και παρένθεση.


Αυτό είναι ιδιαίτερα αληθές αν μπορείτε να επωφεληθούν από ένα καλό πρόγραμμα επεξεργασίας που βοηθά με την εσοχή και χρωματισμό σύνταξης (δοκιμάστε να ρυθμίσετε την παρένθεση σε ένα χρώμα μοιάζει πολύ με το φόντο).


Μπορεί να μην είναι σε θέση να αντικαταστήσουν τη γλώσσα εντελώς και να πάρετε σύνταξη «Ruby», αλλά δεν το χρειάζεστε. Χάρη στην ευελιξία γλώσσα θα μπορούσατε να καταλήξετε με μια διάλεκτο που αισθάνεται σαν να είναι μετά το «στυλ Ruby προγραμματισμού», αν θέλετε, ό, τι αυτό θα σημαίνει για εσάς.


Ξέρω ότι αυτό είναι μόνο μια εμπειρική παρατήρηση, αλλά νομίζω ότι είχα ένα από αυτά τα Lisp στιγμές φώτιση, όταν κατάλαβα αυτό.

 

Ξανά και ξανά, οι νεοφερμένοι να Lisp θέλουν να «ξεφορτωθούν όλα τα παρένθεση.» Διαρκεί για λίγες εβδομάδες. Κανένα σχέδιο για την κατασκευή ενός σοβαρού σύνταξη προγραμματισμού γενικού σκοπού πάνω από το συνηθισμένο πρόγραμμα ανάλυσης S-έκφραση παίρνει ποτέ οπουδήποτε, επειδή οι προγραμματιστές πάντα περάτωση προτιμώντας αυτό που αντιλαμβανόμαστε σήμερα ως «παρένθεση κόλαση.» Χρειάζεται λίγο να συνηθίσει, αλλά όχι πολύ! Μόλις το κάνετε να το συνηθίσεις, και μπορείτε πραγματικά να εκτιμήσετε την πλαστικότητα της προεπιλεγμένης σύνταξη, πηγαίνοντας πίσω στις γλώσσες όπου υπάρχει μόνο ένας τρόπος για να εκφράσουν κάποια συγκεκριμένη δομή προγραμματισμού είναι πολύ τρίψιμο.


Τούτου λεχθέντος, Lisp είναι ένα εξαιρετικό υπόστρωμα για την κατασκευή Χώρου Συγκεκριμένες Γλώσσες. Εξίσου καλή, αν όχι καλύτερα από ό, τι, XML.


Καλή τύχη!

 

Η καλύτερη εξήγηση των Lisp μακροεντολές που έχω δει ποτέ είναι σε


<https://www.youtube.com/watch?v=4NO83wZVT0A>


ξεκινώντας από περίπου 55 λεπτά. Αυτό είναι ένα βίντεο από μια ομιλία που έδωσε ο Peter Seibel, ο συγγραφέας του «Πρακτική Common Lisp», η οποία είναι η καλύτερη Lisp βιβλίο δεν υπάρχει.


Το κίνητρο για την Lisp μακροεντολές είναι συνήθως δύσκολο να το εξηγήσω, γιατί πραγματικά έρχονται σε δική τους σε καταστάσεις που είναι πολύ χρονοβόρες για να παρουσιάσει σε ένα απλό tutorial. Ο Peter έρχεται με ένα μεγάλο παράδειγμα? μπορείτε να το κατανοήσουν πλήρως, και αυτό κάνει καλό, τη σωστή χρήση της Lisp μακροεντολές.


Μπορείτε ρώτησε: «θα μπορούσατε να αλλάξετε τη λειτουργική φύση της LISP σε μια πιο προσανατολισμένη αντικείμενο τη σύνταξη και τη σημασιολογία». Η απάντηση είναι ναι. Στην πραγματικότητα, Lisp αρχικά δεν είχε καμία αντικειμενοστραφή προγραμματισμό σε όλα, δεν προκαλεί έκπληξη δεδομένου ότι η Lisp έχει γύρω από τον τρόπο πριν αντικειμενοστραφή προγραμματισμό! Αλλά όταν έμαθε για πρώτη φορά για OOP το 1978, ήμασταν σε θέση να το προσθέσετε στο Lisp εύκολα, χρησιμοποιώντας, μεταξύ άλλων, μακροεντολές. Τελικά αναπτύχθηκε η Common Lisp Σύστημα αντικειμένου (CLO), ένα πολύ ισχυρό σύστημα προγραμματισμού object-oriented που ταιριάζει κομψά σε Lisp. Το όλο θέμα μπορεί να φορτωθεί ως επέκταση - τίποτα δεν είναι ενσωματωμένο! Όλα γίνονται με μακροεντολές.


Lisp έχει ένα εντελώς διαφορετικό χαρακτηριστικό, που ονομάζεται «μακροεντολές αναγνώστη», που μπορεί να χρησιμοποιηθεί για να επεκτείνει τη σύνταξη επιφάνεια της γλώσσας. Χρησιμοποιώντας μακροεντολές αναγνώστη, μπορείτε να κάνετε sublanguages ​​που έχουν C-ομοειδών ή Ruby-όπως σύνταξη. Έχουν μετατρέψει το κείμενο σε Lisp, εσωτερικά. Αυτά δεν χρησιμοποιούνται ευρέως από τους περισσότερους πραγματικούς Lisp προγραμματιστές, κυρίως επειδή είναι δύσκολο να επεκταθεί το διαδραστικό περιβάλλον ανάπτυξης για να γίνει κατανοητή η νέα σύνταξη. Για παράδειγμα, οι εντολές οδόντωση Emacs θα πρέπει να συγχέεται με ένα νέο συντακτικό. Αν είστε ενεργητικός, όμως, το Emacs είναι επεκτάσιμη πάρα πολύ, και θα μπορούσε να διδάξει σχετικά με το νέο σας λεξιλογικό σύνταξη.

 

Η τακτική μακροεντολές λειτουργούν στις λίστες των αντικειμένων. Συνηθέστερα, τα αντικείμενα αυτά είναι άλλες λίστες (σχηματίζοντας έτσι δέντρα) και σύμβολα, αλλά μπορούν να είναι άλλα αντικείμενα όπως χορδές, hashtables, αντικείμενα καθορίζονται από το χρήστη, κλπ Αυτές οι δομές ονομάζονται [s-EXPS](http://en.wikipedia.org/wiki/S-expression) .


Έτσι, όταν φορτώσετε ένα αρχείο προέλευσης, Lisp compiler σας θα αναλύσει το κείμενο και να παράγουν s-EXPS. Οι μακροεντολές λειτουργούν σε αυτά. Αυτό λειτουργεί μεγάλο και είναι ένα θαυμάσιο τρόπο για να επεκτείνει τη γλώσσα μέσα στο πνεύμα της s-EXPS.


Επιπλέον, η προαναφερθείσα διαδικασία ανάλυσης μπορεί να επεκταθεί μέσω της «μακροεντολές αναγνώστη» που σας επιτρέπουν να προσαρμόσετε τον τρόπο με τον compiler σας μετατρέπει το κείμενο σε s-EXPS. Προτείνω, ωστόσο, ότι θα αγκαλιάσει σύνταξη Lisp, αντί της κάμψης σε κάτι άλλο.


Μπορείτε να ακούγεται λίγο μπερδεμένη όταν αναφέρω «λειτουργικής φύσεως» Lisp και «σύνταξη object-oriented» ρουμπινιού. Δεν είμαι σίγουρος τι «σύνταξη object-oriented» υποτίθεται ότι είναι, αλλά Lisp είναι μια γλώσσα multi-πρότυπο και υποστηρίζει αντικειμενοστραφή προγραμματισμό *Εξαιρετικά* καλά.


BTW, όταν λέω Lisp, εννοώ [Common Lisp](http://en.wikipedia.org/wiki/Common_Lisp) .


Σας προτείνω να βάλετε τις προκαταλήψεις σας μακριά και να [δώσει Lisp μια ειλικρινή δρόμο](http://gigamonkeys.com/book/) .

 

Αυτό που ζητούν είναι κάπως σαν να ζητάμε από το πώς να γίνει ένας εμπειρογνώμονας chocolatier ώστε να μπορείτε να αφαιρέσετε όλα αυτά τα κολαστήρια καφέ πράγματα από το αγαπημένο σας κέικ σοκολάτας.

 

Παρένθεση κόλαση; Δεν βλέπω καμία περισσότερες παρένθεση σε:



```
(function toto)

```

σε σχέση με:



```
function(toto);

```

Και στο



```
(if tata (toto)
  (titi)
  (tutu))

```

όχι περισσότερο από ό, τι σε:



```
if (tata)
  toto();
else
{
  titi();
  tutu();
}

```

Βλέπω λιγότερο παρένθεση και «?» αν και.

 

Ναι, μπορείτε να αλλάξετε ριζικά τη σύνταξη, και ακόμη και να ξεφύγει «η παρένθεση κόλαση». Γι 'αυτό θα πρέπει να καθορίσει μια νέα σύνταξη αναγνώστη. Κοίτα σε μακροεντολές αναγνώστη.


Κάνω ύποπτο, ωστόσο, ότι για να φτάσει στο επίπεδο της Lisp εμπειρία να προγραμματίσετε όπως μακροεντολές, θα πρέπει να βυθιστείτε στη γλώσσα σε τέτοιο βαθμό που θα εξετάσει πλέον Parenthèse «κόλαση». Δηλαδή από τη στιγμή που ξέρουν πώς να τις αποφύγετε, θα έχουν έρθει για να τους δεχτούν ως ένα καλό πράγμα.

 

δείτε αυτό το παράδειγμα για το πώς οι μακροεντολές αναγνώστης μπορεί να επεκτείνει το ψεύδισμα αναγνώστη με σύνθετες εργασίες, όπως η XML υφής:


<http://common-lisp.net/project/cl-quasi-quote/present-class.html>


αυτό το **χρήστη βιβλιοθήκη** συγκεντρώνει τα στατικά μέρη της XML σε συστοιχίες κυριολεκτική byte κωδικοποίηση UTF-8 κατά τη μεταγλώττιση που είναι έτοιμα να γράψω-sequence'd στο ρεύμα δικτύου. και μπορούν να χρησιμοποιηθούν σε κανονικές Lisp μακροεντολές, είναι ορθογώνια ... η τοποθέτηση των επιρροών χαρακτήρα κόμμα που τα μέρη είναι σταθερά και τα οποία θα πρέπει να αξιολογούνται κατά το χρόνο εκτέλεσης.


περισσότερες λεπτομέρειες διαθέσιμες στο: <http://common-lisp.net/project/cl-quasi-quote/>


ένα άλλο έργο που για Common Lisp επεκτάσεις σύνταξη: <http://common-lisp.net/project/cl-syntax-sugar/>

 

Αν θέλετε lisp να μοιάζουν Ruby χρησιμοποιούν Ruby. 


Είναι δυνατή η χρήση Ruby (και Python) σε ένα πολύ ψεύδισμα, όπως τον τρόπο που είναι ένας από τους κύριους λόγους που έχουν κερδίσει την αποδοχή τόσο γρήγορα.

 

Μία από τις χρήσεις των μακροεντολών που φύσηξε το μυαλό μου ήταν η μεταγλώττιση χρόνο επαλήθευση των αιτήσεων SQL κατά της DB.


Μόλις συνειδητοποιήσετε ότι έχετε την πλήρη γλώσσα στο χέρι κατά τη μεταγλώττιση χρόνο, ανοίγει ενδιαφέρουσες νέες προοπτικές. Πράγμα που σημαίνει, επίσης, μπορείτε να πυροβολήσει τον εαυτό σας στο πόδι σε ενδιαφέροντες νέους τρόπους (όπως η απόδοση συλλογής δεν είναι να αναπαραχθεί, το οποίο μπορεί πολύ εύκολα να μετατραπεί σε εφιάλτη debugging).

 

Είναι μια δύσκολη ερώτηση. Από Lisp είναι ήδη δομικά τόσο κοντά σε ένα δέντρο ανάλυσης η διαφορά ανάμεσα σε ένα μεγάλο αριθμό των μακροεντολών και την εφαρμογή της δικής σας μίνι-γλώσσα σε μια γεννήτρια parser δεν είναι πολύ σαφής. Όμως, εκτός από τις παρένθεσης ανοίγματος και κλεισίματος, θα μπορούσε πολύ εύκολα να καταλήξουν σε κάτι που δεν μοιάζει καθόλου με Lisp.

 

@sparkes


Μερικές φορές LISP είναι η σαφής επιλογή γλώσσας, δηλαδή επεκτάσεις Emacs. Είμαι σίγουρος ότι θα μπορούσε να χρησιμοποιήσει Ruby να επεκτείνει το Emacs, αν το ήθελα, αλλά Emacs έχει σχεδιαστεί για να επεκταθεί με LISP, έτσι φαίνεται να έχει νόημα να το χρησιμοποιήσετε σε αυτή την κατάσταση.

 