Hoe ver kan LISP macro's gaan?

stemmen
43

Ik heb veel dat LISP syntax kunnen herdefiniëren on the fly, vermoedelijk met macro's te lezen. Ik ben benieuwd hoe ver gaat dit ook daadwerkelijk te gaan? Kunt u de taal structuur zo veel dat het borderline wordt een compiler voor een andere taal te herdefiniëren? Bijvoorbeeld, kon u van het functionele karakter van LISP te veranderen in een meer objectgeoriënteerde syntaxis en semantiek, misschien zeggen met syntax dichter bij iets als Ruby?

Vooral, is het mogelijk om zich te ontdoen van de haakjes de hel met behulp van macro's te krijgen? Ik heb geleerd genoeg (Emacs-) LISP om Emacs te passen met mijn eigen micro-functies, maar ik ben erg benieuwd hoe ver macro's kunnen gaan in het aanpassen van de taal.

De vraag is gesteld op 05/08/2008 om 08:32
bron van user
In andere talen...                            


14 antwoorden

stemmen
33

Dat is een heel goede vraag.

Ik denk dat het genuanceerd, maar zeker verantwoording:

Macro's zijn niet vast te zitten in 's-uitingen. Zie de LOOP macro voor een zeer complexe taal geschreven met trefwoorden (symbolen). Dus, terwijl je kan beginnen en eindigen de lus met haakjes, binnen het heeft zijn eigen syntax.

Voorbeeld:

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

Dat gezegd zijnde, de meeste eenvoudige macro gewoon gebruik maken van s-uitingen. En je zou worden "geplakt" met behulp van hen.

Maar s-uitingen, zoals Sergio heeft beantwoord, start naar rechts te voelen. De syntaxis krijgt uit de weg en je begint codering in de syntax boom.

Zoals voor de lezer macro's, ja, je denkbaar schrijven zoiets als dit:

#R{
      ruby.code.goes.here
  }

Maar zou je nodig hebt om je eigen Ruby syntax parser schrijven.

U kunt ook na te bootsen enkele van de Ruby-constructen, zoals blokken, met macro's die samen te stellen om de bestaande Lisp constructies.

#B(some lisp (code goes here))

zou vertalen naar

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

Zie deze pagina voor hoe dit te doen.

antwoordde op 15/09/2008 om 16:07
bron van user

stemmen
20

Ja, u kunt de syntaxis herdefiniëren zodat Lisp wordt een compiler. Dit doe je met behulp van "Reader Macro's", die anders dan de normale "Compiler Macro's" die je waarschijnlijk denkt aan zijn.

Common Lisp heeft de ingebouwde mogelijkheid om nieuwe syntax definiëren voor de lezer en de lezer macro's om die syntax verwerken. Deze verwerking gebeurt op lees-time (die vóór komt compileren of eval tijd). Voor meer informatie over het definiëren van de lezer macro's in Common Lisp vindt u in de Common Lisp Hyperspec - je wilt lezen Ch. 2, "Syntax" en Ch. 23, "Reader" . (Ik geloof Scheme heeft dezelfde faciliteit, maar ik ben niet zo vertrouwd met het - zie de Regeling bronnen voor de Arc programmeertaal ).

Als een eenvoudig voorbeeld, laten we aannemen dat u wilt Lisp om accolades in plaats van haakjes. Dit vereist iets als het volgende lezer definities:

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

Je vertelt Lisp dat de {is als een (en dat het} is als a). Dan is een functie (maakt u lcurly-brace-reader) dat de lezer zal roepen wanneer hij ziet een {, en u set-macro-charactermet die functie van de {toe te wijzen. Dan zeg je Lisp dat (en) zijn, zoals [en] (dat wil zeggen, niet zinvol syntaxis).

Andere dingen die je zou kunnen doen omvatten, bijvoorbeeld, het creëren van een nieuwe string syntax of met [en] om in-fix notatie omsluiten en verwerken in de S-uitingen.

U kunt ook veel verder gaan dan dit, het herdefiniëren van de gehele syntax met uw eigen macro personages die zal leiden tot acties in de lezer, zodat de lucht is echt de limiet. Dit is slechts één van de redenen waarom Paul Graham en anderen blijven zeggen dat Lisp is een goede taal waarin een compiler schrijven.

antwoordde op 16/09/2008 om 20:28
bron van user

stemmen
16

Ik ben niet een Lisp expert, heck ik ben niet eens een Lisp programmeur, maar na een beetje experimenteren met de taal kwam ik tot de conclusie dat na een tijdje het haakje beginnen steeds 'onzichtbaar' en u begint met het zien van de code je wilt dat het is. Je begint meer aandacht voor de syntactische constructies die u maakt via s-exprs en macro's, en minder op de lexicale vorm van de tekst van de lijsten en haakjes.

Dit is vooral het geval als u profiteren van een goede editor die helpt bij het deukje en syntaxiskleuren (probeer het instellen van de haakjes om een ​​kleur zeer vergelijkbaar met de achtergrond).

Je zou niet in staat zijn om de taal volledig te vervangen en krijgen 'Ruby' syntax, maar je hoeft het niet nodig. Dankzij de taal flexibiliteit die je zou kunnen eindigen met een dialect dat voelt alsof je naar aanleiding van de 'Ruby stijl van de programmering' als u wilt, wat dat zou betekenen voor jou.

Ik weet dat dit is slechts een empirische waarneming, maar ik denk dat ik had een van die Lisp verlichting momenten dat ik dit gerealiseerd.

antwoordde op 26/08/2008 om 10:49
bron van user

stemmen
15

over en weer, en nieuwkomers op Lisp willen "te ontdoen van alle haakjes." Het duurt een paar weken. Geen enkel project om een ​​ernstige algemene doeleinden programmering syntax te bouwen op de top van de gebruikelijke S-expression parser krijgt ooit ergens, omdat programmeurs steevast liquideren liever wat je op dit moment te zien als "haakjes de hel." Het is even wennen, maar niet veel! Zodra je went er wel aan, en je kunt echt genieten van de plasticiteit van de standaard syntax, terug te gaan naar talen waar er maar één manier om een ​​bepaalde programmering constructie Express is echt rooster.

Dat gezegd zijnde, Lisp is een uitstekend substraat voor het bouwen van Domain Specific Languages. Net zo goed als, zo niet beter dan, XML.

Succes!

antwoordde op 16/09/2008 om 20:29
bron van user

stemmen
12

De beste verklaring van Lisp macro's die ik ooit heb gezien is op

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

vanaf ongeveer 55 minuten in. Dit is een video van een lezing gegeven door Peter Seibel, de auteur van "Practical Common Lisp", dat is de beste Lisp boek er is.

De motivatie voor Lisp macro's is meestal moeilijk uit te leggen, omdat ze echt in hun eigen in situaties die te lang te presenteren in een eenvoudige tutorial zijn gekomen. Peter komt met een goed voorbeeld; je kunt het volledig begrijpen, en het maakt goed, het juiste gebruik van Lisp macro's.

Je vroeg: "kon je van het functionele karakter van LISP te veranderen in een meer objectgeoriënteerde syntax en semantiek". Het antwoord is ja. In feite, Lisp oorspronkelijk leverde geen object-georiënteerd programmeren helemaal hebben, niet verrassend aangezien Lisp is al sinds zo geweest voor object-georiënteerd programmeren! Maar toen we voor het eerst in 1978 geleerd over OOP, waren we in staat om het toe te voegen aan gemakkelijk LISP, met behulp van, onder andere, macro's. Uiteindelijk werd de Common Lisp Object System (CLOS) werd ontwikkeld, een zeer krachtige object-georiënteerd programmeren systeem dat elegant past in Lisp. De hele zaak kan worden geladen als een uitbreiding - niets is ingebouwd! Het is allemaal gedaan met macro's.

Lisp heeft een geheel andere functie, genaamd "lezer macro's", die kan worden gebruikt om het oppervlak syntax van de taal uitstrekken. Met behulp lezer macro's, kunt u subtalen dat C-achtige of Ruby-achtige syntax hebben te maken. Zij zetten de tekst in Lisp, intern. Deze zijn niet op grote schaal gebruikt door de meeste echte Lisp programmeurs, vooral omdat het moeilijk is om de interactieve ontwikkelomgeving te breiden tot de nieuwe syntaxis te begrijpen. Bijvoorbeeld, zou Emacs inspringen commando's worden verward door een nieuwe syntaxis. Als je energiek bent, hoewel, Emacs is uitbreidbaar ook, en je kon leren over uw nieuwe lexicale syntax.

antwoordde op 05/10/2008 om 16:03
bron van user

stemmen
11

Regelmatige macro's werken op lijsten van objecten. Meestal zijn deze objecten zijn andere lijsten (waardoor de vorming van bomen) en symbolen, maar ze kunnen ook andere voorwerpen, zoals strijkers, hashtables, door de gebruiker gedefinieerde objecten, enz. Deze structuren worden genoemd s-EXPS .

Dus, als je een bron bestand te laden, uw Lisp compiler zal de tekst ontleden en te produceren s-EXPS. Macro's werken op deze. Dit werkt geweldig en het is een geweldige manier om de taal binnen de geest van de s-EXPS verlengen.

Bovendien kan de hiervoor genoemde parsing proces worden uitgebreid door middel van "reader macros" waarmee u de manier waarop uw compiler verandert tekst in s-EXPS aanpassen. Ik stel voor, echter, dat u Lisp's syntax te omarmen in plaats van het in iets anders te buigen.

Je klinkt een beetje in de war wanneer u "functionele karakter" Lisp en Ruby's "object-georiënteerde syntax" noemen. Ik weet niet zeker wat "object-georiënteerde syntax" hoort te zijn, maar Lisp is een multi-paradigma taal en het ondersteunt objectgeoriënteerd programmeren extremelly goed.

Trouwens, als ik zeg Lisp, bedoel ik Common Lisp .

Ik stel voor dat je weg zet je vooroordelen en geven Lisp een eerlijk gaan .

antwoordde op 26/08/2008 om 10:36
bron van user

stemmen
9

Wat je vraagt ​​is een beetje hetzelfde als vragen hoe je een expert chocolatier worden, zodat u al die helse bruine spul van uw favoriete chocoladetaart kan verwijderen.

antwoordde op 17/09/2008 om 13:14
bron van user

stemmen
9

Haakjes hel? Ik zie niet meer tussen haakjes in:

(function toto)

dan in:

function(toto);

En in

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

niet meer dan in:

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

Ik zie minder beugels en ';' though.

antwoordde op 16/09/2008 om 17:23
bron van user

stemmen
6

Ja, u kunt fundamentele verandering van de syntax, en zelfs te ontsnappen "tussen haakjes de hel". Voor dat je nodig hebt om een ​​nieuwe lezer syntax definiëren. Kijk in lezer macro's.

Ik doe vermoeden echter dat het niveau van Lisp deskundigheid te bereiken om een ​​dergelijke macro's je nodig hebt om jezelf onder te dompelen in de taal zodanig dat u niet langer zal overwegen parenthese "hel" te programmeren. Dat wil zeggen door de tijd dat je weet hoe ze te vermijden, zul je zijn gekomen om hen te accepteren als een goede zaak.

antwoordde op 15/09/2008 om 13:07
bron van user

stemmen
2

zie dit voorbeeld van de manier waarop de lezer macro het lisp lezer met complexe taken, zoals XML templating kunnen verlengen:

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

deze gebruiker bibliotheek stelt de statische delen van de XML in UTF-8-codering letterlijke bytearrays tijdens het compileren die klaar zijn om te schrijven-sequence'd in het netwerk terecht kunnen komen. en ze kunnen worden gebruikt voor normale lisp macro's, zijn ze orthogonaal ... de plaatsing van de kommateken invloeden welke delen constant en die moeten worden geëvalueerd tijdens de uitvoering.

Meer details zijn beschikbaar op: http://common-lisp.net/project/cl-quasi-quote/

een ander project dat voor Common Lisp syntax extensies: http://common-lisp.net/project/cl-syntax-sugar/

antwoordde op 17/09/2008 om 01:30
bron van user

stemmen
2

Als u wilt lisp te laten uitzien als Ruby gebruiken Ruby.

Het is mogelijk om Ruby (en Python) te gebruiken in een zeer lisp achtige manier dat is een van de belangrijkste redenen die zij hebben aanvaard zo snel gewonnen.

antwoordde op 05/08/2008 om 08:40
bron van user

stemmen
1

Een van de toepassingen van macro's die blies mijn gedachten was het compile-time controle van de SQL-aanvragen tegen DB.

Zodra je je realiseert u de volledige taal bij de hand tijdens het compileren, het opent nieuwe perspectieven. Dat betekent ook je jezelf in de voet schieten in interessante nieuwe manieren (zoals rendering compilatie niet reproduceerbaar, die zeer gemakkelijk kan veranderen in een debugging nachtmerrie).

antwoordde op 19/09/2008 om 11:43
bron van user

stemmen
1

Het is een lastige vraag. Omdat lisp is al structureel zo dicht bij een parse boom het verschil tussen een groot aantal macro's en de uitvoering van uw eigen mini-taal in een parser generator is niet erg duidelijk. Maar, behalve voor het openen en sluiten paren, kun je heel gemakkelijk eindigen met iets dat niets als lisp lijkt.

antwoordde op 06/08/2008 om 13:14
bron van user

stemmen
1

@sparkes

Soms LISP is de duidelijke taal keuze, namelijk Emacs extensies. Ik weet zeker dat ik kon Ruby gebruiken om Emacs te verlengen als ik wilde, maar Emacs is ontworpen om te worden uitgebreid met LISP, zo lijkt het zinvol om het te gebruiken in die situatie.

antwoordde op 05/08/2008 om 08:45
bron van user

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more