0
votes

La macro commune LISP à développer une liste d'arguments passée comme repos comme suit: (FOO (Agrandir la barre 100 200 300)) => (Barre 100) (barre 200) (barre 300) (barre 300))

Désolé pour le titre maladroit, mais j'ai du mal à décrire ce que je cherche en quelques mots ...

Je travaille sur un projet COMMON LISP DSL et je vous demande si ce qui suit est possible:

Le DSL pourrait avoir quelques fonctions

(défunteur FOO (et reste de repos))

et

(barre de défunement (arg))

qui sera utilisé de la manière suivante:

(FOO (barre 100) (barre 200) (barre 300) (barre 400) (barre 500)) etc.

Maintenant, c'est beaucoup de taper redondant, alors je me demande s'il est possible de créer une macro Expander ça va permettre

(FOO (Développer la barre 100 200 300 400 500))

sans changer foo lui-même?


0 commentaires

3 Réponses :


1
votes

Il n'y a pas besoin de macro: xxx


2 commentaires

Hmm true, en utilisant appliquer est toujours une option, même si je me demandais si c'était possible sans. Dans le contexte, je pense que cela serait plus intuitif si vous pouviez utiliser la même fonction (la DSL est destinée aux personnes qui ne connaissent pas vraiment CL en soi)


"HMM True, l'utilisation d'applications est toujours une option" - pas toujours, uniquement pour les fonctions, pas pour les macros. ;-)



1
votes

Non, cela ne peut pas être fait sans changer la signature des fonctions que vous définissez (ou éventuellement à l'aide d'une chose velue qui redéfinit la macroexpansion): vous avez ce que j'appelle une incidence d'impédance «Spread / Noscread Impédation» qui ne peut pas Soyez résolu avec une macro standard dans cl.

une fonction 'nosplead' est une fonction qui enveloppe tous ses arguments en une formelle. Une fonction «spread» a un argument formel par argument. J'ai appris ces termes lors de l'utilisation interlisp: ils peuvent le prédire, mais ils semblent être surtout inutilisés maintenant. Les fonctions CL peuvent être uniquement partiellement nosplead ( (foo bar & repos plus) ). Votre foo est NOSPREAD.

A EMPLÉDANCE DE SPARECTION / NOSPREAD EMPÉDANCE Est-ce que vous avez une fonction de propagation, mais que vous voulez une norme, ou vice Versa . C'est presque toujours un signe d'un problème de conception. La solution de contournement pour les problèmes de propagation / nos couvre implique généralement appliquer .

Votre problème est que foo est une fonction nosplead: il transforme tous ses arguments en une liste , mais vous voulez que la macro la traite comme une fonction de propagation, ce qui lui remet une liste unique d'arguments.

en particulier, dans cl une expression comme (x (Y ...)) / code> ne peut jamais être transformé en (x a1 a2 ...) pour tout y , fonction ou macro (mais voir ci-dessous), et c'est ce dont vous avez besoin pour arriver.

Dans votre cas, vous voulez quelque chose comme xxx

se transformer en xxx

et Cela ne peut pas arriver.

Il y a eu des Lisps qui avaient été des choses qui avaient appelé des «macros d'épissage» dans lesquelles une expansion d'une macro pourrait être «épissée» dans une liste, de la manière dont fait pour BackQuote. Il est peut-être qu'il existe des packages macro épisseurs pour cl, et il peut même être qu'ils sont portables: vous pouvez avoir un long chemin avec * macroexpand-crochet * . Mais les macros CL standard ne peuvent pas faire cela.


2 commentaires

Hein, merci pour la réponse détaillée et merci pour la mise à jour de la terminologie. Cela étant dit, à la recherche d'un paquet tourné deux qui semblent faire exactement ce que vous décrivez: QuickRef.common-lisp.net/cl-splicing-macro.html et QuickRef.common-lisp.net/quasiquote-2.0.html


@Ellipsenpark: Oui, j'étais vaguement conscient de cela. Autant que je sache, il utilise * macroexpand-hameçon * pour faire son travail. Il m'empêche un peu que cl ne possède pas plus de variables de crochet comme ça, comme ils sont très flexibles: j'ai suggéré une fois que les implémentations pouvaient être d'accord sur les quasi-standard, mais les gens ne l'aimaient pas, alors j'ai abandonné



0
votes

Il peut être utile de scinder votre DSL en deux parties, une version plus simple que vous programmez contre et une version plus conviviale. Par exemple: xxx


0 commentaires