Jusqu'où les macros LISP peuvent-elles aller?

Translate

J'ai beaucoup lu que LISP peut redéfinir la syntaxe à la volée, probablement avec des macros. Je suis curieux de savoir jusqu'où cela va réellement? Pouvez-vous redéfinir la structure du langage au point qu'il devienne un compilateur pour un autre langage? Par exemple, pourriez-vous changer la nature fonctionnelle de LISP en une syntaxe et une sémantique plus orientées objet, peut-être dire avoir une syntaxe plus proche de quelque chose comme Ruby?

Surtout, est-il possible de se débarrasser de l'enfer des parenthèses en utilisant des macros? J'ai suffisamment appris (Emacs-) LISP pour personnaliser Emacs avec mes propres micro-fonctionnalités, mais je suis très curieux de savoir jusqu'où les macros peuvent aller dans la personnalisation du langage.

This question and all comments follow the "Attribution Required."

Toutes les réponses

Translate

C'est une très bonne question.

Je pense que c'est nuancé mais certainement responsable:

Les macros ne sont pas bloquées dans les expressions s. Voir la macro LOOP pour un langage très complexe écrit à l'aide de mots-clés (symboles). Ainsi, bien que vous puissiez commencer et terminer la boucle avec des parenthèses, à l'intérieur, elle a sa propre syntaxe.

Exemple:

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

Cela étant dit, la plupart des macros simples utilisent simplement des s-expressions. Et vous seriez "coincé" en les utilisant.

Mais les expressions s, comme Sergio a répondu, commencent à se sentir bien. La syntaxe disparaît et vous commencez à coder dans l'arborescence de la syntaxe.

En ce qui concerne les macros de lecture, oui, vous pourriez éventuellement écrire quelque chose comme ceci:

#R{
      ruby.code.goes.here
  }

Mais vous devez écrire votre propre analyseur de syntaxe Ruby.

Vous pouvez également imiter certaines des constructions Ruby, comme des blocs, avec des macros qui se compilent avec les constructions Lisp existantes.

#B(some lisp (code goes here))

se traduirait par

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

Voircette pagepour savoir comment le faire.

La source
Translate

Oui, vous pouvez redéfinir la syntaxe pour que Lisp devienne un compilateur. Vous faites cela en utilisant des "Macros de lecteur", qui sont différentes des "Macros de compilateur" normales auxquelles vous pensez probablement.

Common Lisp a la fonction intégrée de définir une nouvelle syntaxe pour les macros de lecture et de lecture pour traiter cette syntaxe. Ce traitement est effectué au moment de la lecture (qui vient avant la compilation ou l'évaluation). Pour en savoir plus sur la définition des macros de lecture dans Common Lisp, consultez le Common Lisp Hyperspec - vous voudrez lireCh. 2, "Syntaxe"etCh. 23, "Lecteur". (Je crois que Scheme a la même fonctionnalité, mais je ne suis pas aussi familier avec elle - voir leSources du schémapour leLangage de programmation Arc).

À titre d'exemple simple, supposons que vous souhaitiez que Lisp utilise des accolades plutôt que des parenthèses. Cela nécessite quelque chose comme les définitions de lecteur suivantes:

;; { 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 #\( #\[ )

Vous dites à Lisp que le {est comme a (et que le} est comme a). Ensuite, vous créez une fonction (lcurly-brace-reader) que le lecteur appellera chaque fois qu'il voit un {, et que vous utilisezset-macro-characterpour attribuer cette fonction au {. Ensuite, vous dites à Lisp que (et) sont comme [et] (c'est-à-dire que la syntaxe n'est pas significative).

D'autres choses que vous pourriez faire incluent, par exemple,création d'une nouvelle syntaxe de chaîneou en utilisant [et] pour inclure la notation in-fix et la traiter en S-expressions.

Vous pouvez également aller bien au-delà de cela, en redéfinissant toute la syntaxe avec vos propres caractères de macro qui déclencheront des actions dans le lecteur, de sorte que le ciel est vraiment la limite. Ce n'est qu'une des raisons pour lesquellesPaul Grahametautrescontinuez à dire que Lisp est un bon langage pour écrire un compilateur.

La source
Translate

Je ne suis pas un expert Lisp, diable je ne suis même pas un programmeur Lisp, mais après un peu d'expérimentation avec le langage, je suis arrivé à la conclusion qu'après un certain temps, les parenthèses commencent à devenir `` invisibles '' et vous commencez à voir le code comme vous voulez que ce soit le cas. Vous commencez à accorder plus d'attention aux constructions syntaxiques que vous créez via les s-expr et les macros, et moins à la forme lexicale du texte des listes et des parenthèses.

Cela est particulièrement vrai si vous profitez d'un bon éditeur qui aide à l'indentation et à la coloration de la syntaxe (essayez de définir la parenthèse sur une couleur très similaire à l'arrière-plan).

Vous ne pourrez peut-être pas remplacer complètement le langage et obtenir la syntaxe «Ruby», mais vous n'en avez pas besoin. Grâce à la flexibilité du langage, vous pourriez finir avec un dialecte qui donne l'impression de suivre le «style de programmation Ruby» si vous le souhaitez, quoi que cela signifie pour vous.

Je sais que ce n'est qu'une observation empirique, mais je pense que j'ai eu un de ces moments d'illumination Lisp quand j'ai réalisé cela.

La source
Translate

À maintes reprises, les nouveaux venus dans Lisp veulent "se débarrasser de toutes les parenthèses". Cela dure quelques semaines. Aucun projet visant à construire une syntaxe de programmation à usage général sérieuse en plus de l'analyseur d'expression S habituel n'obtient jamais nulle part, car les programmeurs finissent invariablement par préférer ce que vous percevez actuellement comme «l'enfer des parenthèses». Il faut un peu de temps pour s'y habituer, mais pas beaucoup! Une fois que vous vous y êtes habitué et que vous pouvez vraiment apprécier la plasticité de la syntaxe par défaut, revenir aux langages où il n'y a qu'une seule façon d'exprimer une construction de programmation particulière est vraiment difficile.

Cela étant dit, Lisp est un excellent substrat pour la construction de langages spécifiques au domaine. Aussi bon, sinon meilleur, que XML.

Bonne chance!

La source
Translate

La meilleure explication des macros Lisp que j'ai jamais vue est à

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

à partir d'environ 55 minutes. Ceci est une vidéo d'une conférence donnée par Peter Seibel, l'auteur de "Practical Common Lisp", qui est le meilleur manuel Lisp qui soit.

La motivation des macros Lisp est généralement difficile à expliquer, car elles prennent tout leur sens dans des situations trop longues à présenter dans un simple tutoriel. Peter propose un excellent exemple; vous pouvez le saisir complètement, et cela permet une bonne utilisation des macros Lisp.

Vous avez demandé: "pourriez-vous changer la nature fonctionnelle de LISP en une syntaxe et une sémantique plus orientées objet". La réponse est oui. En fait, Lisp n'avait à l'origine aucune programmation orientée objet, ce qui n'est pas surprenant puisque Lisp existe depuis bien avant la programmation orientée objet! Mais lorsque nous avons découvert la POO pour la première fois en 1978, nous avons pu l'ajouter facilement à Lisp, en utilisant, entre autres, des macros. Finalement, le Common Lisp Object System (CLOS) a été développé, un système de programmation orienté objet très puissant qui s'intègre élégamment dans Lisp. Le tout peut être chargé en tant qu'extension - rien n'est intégré! Tout est fait avec des macros.

Lisp a une fonctionnalité entièrement différente, appelée "macros de lecture", qui peut être utilisée pour étendre la syntaxe de surface du langage. En utilisant des macros de lecteur, vous pouvez créer des sous-langages qui ont une syntaxe de type C ou Ruby. Ils transforment le texte en Lisp, en interne. Ceux-ci ne sont pas largement utilisés par la plupart des vrais programmeurs Lisp, principalement parce qu'il est difficile d'étendre l'environnement de développement interactif pour comprendre la nouvelle syntaxe. Par exemple, les commandes d'indentation Emacs seraient déroutées par une nouvelle syntaxe. Si vous êtes énergique, cependant, Emacs est également extensible et vous pouvez lui apprendre votre nouvelle syntaxe lexicale.

La source
Translate

Les macros régulières fonctionnent sur des listes d'objets. Le plus souvent, ces objets sont d'autres listes (formant ainsi des arbres) et des symboles, mais ils peuvent être d'autres objets tels que des chaînes, des tables de hachage, des objets définis par l'utilisateur, etc. Ces structures sont appeléess-exps.

Ainsi, lorsque vous chargez un fichier source, votre compilateur Lisp analysera le texte et produira des s-exps. Les macros fonctionnent sur ces derniers. Cela fonctionne très bien et c'est une merveilleuse façon d'étendre la langue dans l'esprit de s-exps.

De plus, le processus d'analyse susmentionné peut être étendu par le biais de "macros de lecture" qui vous permettent de personnaliser la façon dont votre compilateur transforme le texte en s-exps. Je suggère cependant que vous adoptiez la syntaxe de Lisp au lieu de la plier en quelque chose d'autre.

Vous semblez un peu confus lorsque vous mentionnez la «nature fonctionnelle» de Lisp et la «syntaxe orientée objet» de Ruby. Je ne sais pas ce que la "syntaxe orientée objet" est censée être, mais Lisp est un langage multi-paradigme et il prend en charge la programmation orientée objetextrêmementbien.

BTW, quand je dis Lisp, je veux direCommon Lisp.

Je vous suggère de mettre vos préjugés de côté etdonnez à Lisp une chance honnête.

La source
Translate

Parenthèse enfer? Je ne vois plus de parenthèses dans:

(function toto)

que dans:

function(toto);

Et en

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

pas plus que dans:

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

Je vois moins de crochets et de ';' bien que.

La source
Translate

Ce que vous demandez, c'est un peu comme demander comment devenir un chocolatier expert afin que vous puissiez retirer tout ce truc brun infernal de votre gâteau au chocolat préféré.

La source
HD.
Translate

Oui, vous pouvez changer fondamentalement la syntaxe, et même échapper à "l'enfer des parenthèses". Pour cela, vous devrez définir une nouvelle syntaxe de lecteur. Regardez dans les macros de lecteur.

Je soupçonne cependant que pour atteindre le niveau d'expertise Lisp pour programmer de telles macros, vous devrez vous immerger dans le langage à un point tel que vous ne considérerez plus ces parenthèses comme "l'enfer". C'est-à-dire que lorsque vous saurez comment les éviter, vous en serez venu à les accepter comme une bonne chose.

La source
Translate

Si vous voulez que lisp ressemble à Ruby, utilisez Ruby.

Il est possible d'utiliser Ruby (et Python) d'une manière très simple, ce qui est l'une des principales raisons pour lesquelles ils ont été acceptés si rapidement.

La source
Translate

voyez cet exemple de la façon dont les macros de lecteur peuvent étendre le lecteur lisp avec des tâches complexes telles que la création de modèles XML:

http://common-lisp.net/project/cl-quasi-quote/���z {rV���m�Xm

cebibliothèque utilisateurcompile les parties statiques du XML dans des tableaux d'octets littéraux encodés en UTF-8 au moment de la compilation qui sont prêts à être séquencés en écriture dans le flux réseau. et elles sont utilisables dans les macros lisp normales, elles sont orthogonales ... le placement de la virgule influence quelles parties sont constantes et qui doivent être évaluées à l'exécution.

plus de détails disponibles sur:http://common-lisp.net/project/cl-quasi-quote/

un autre projet qui pour les extensions de syntaxe Common Lisp:http://common-lisp.net/project/cl-syntax-sugar/

La source
Translate

@parkes

Parfois, LISP est le choix de langage clair, à savoir les extensions Emacs. Je suis sûr que je pourrais utiliser Ruby pour étendre Emacs si je le voulais, mais Emacs a été conçu pour être étendu avec LISP, il semble donc logique de l'utiliser dans cette situation.

La source
Translate

C'est une question délicate. Puisque lisp est déjà structurellement si proche d'un arbre d'analyse, la différence entre un grand nombre de macros et l'implémentation de votre propre mini-langage dans un générateur d'analyseur n'est pas très claire. Mais, à l'exception du paren d'ouverture et de fermeture, vous pourriez très facilement vous retrouver avec quelque chose qui ne ressemble en rien à un lisp.

La source
Translate

L'une des utilisations des macros qui m'a époustouflé était la vérification à la compilation des requêtes SQL par rapport à DB.

Une fois que vous réalisez que vous avez le langage complet à portée de main au moment de la compilation, cela ouvre de nouvelles perspectives intéressantes. Ce qui signifie également que vous pouvez vous tirer une balle dans le pied de nouvelles manières intéressantes (comme le rendu de la compilation non reproductible, qui peut très facilement se transformer en cauchemar de débogage).

La source