Hacker News new | past | comments | ask | show | jobs | submit login
Macros in Perl6 (strangelyconsistent.org)
64 points by drewr on Oct 18, 2011 | hide | past | favorite | 12 comments



This is interesting. You can manipulate the AST in other languages of course, for example Python. However these ASTs are so difficult to handle that programmers don't really want to work with them (see point 12. on bottom of the page http://norvig.com/python-lisp.html).

I think Paul Graham wrote that any language implementing macros with Lisp-power will effectively have to introduce something that is 'as bad or worse than the parenthesis'. [1] It will be interesting to see how this will play out in Perl6.

However the example given in this article is pretty limited, so I think we can't really tell based on that. It also begs the question 'Why not use a function?', i.e. it is not a case where one needs a macro. It will be interesting to see how Perl6 handles real macro use cases where you have to do heavy AST manipulation. I think here the Lisp syntax is really showing its strengths because you don't have to think in terms of a different representation that you don't have in front of you.

[1] See text after the 1-9 list. http://www.paulgraham.com/icad.html

Edit: Better source for [1].


It also begs the question 'Why not use a function?', i.e. it is not a case where one needs a macro

The (last) example is best being a macro because it avoids running that crazily-expensive-computation() whereas a function would evaluate it.


The argument on the delayed execution issue is that you could just wrap crazily-expensive-computation() in a lambda/sub that is executed conditionally.


Indeed. However I do like the fact that Perl6 macros & functions use the same calling syntax and so are often interchangeable.


Nice post. Puts more flesh on the bone than some previous examples i've seen (for eg: http://en.wikipedia.org/wiki/Perl_6#Macros).


And this is called the good kind of macros.. i'm not sure if i want to ever see someone manipulating the AST in his code.. i don't know Lisp and he says that this is what makes Lisp the awesome language it is, but to me it sounds scary and dangerous and inconsistent..


Macros are just a different sort of abstraction. It can be used to solve some problems very elegantly and it can be used to create an incomprehensible mess.

A programmer who has never heard of exceptions may say: "What, so exceptions can interrupt the normal program flow at any time!?" or "Why would I ever want to handle error conditions at a different part of the program? I handle errors right after every function call." or "Exceptions sound scary and inconsistent".

A programmer who has never heard of garbage collection may say: "What, I can't tell ahead of time how much memory my program is going to use?", "I want to know when my program allocates memory and frees it. This shouldn't happen nondeterministically!" or "Automatic memory management sounds scary and unpredictable."


I am a Lisp newbie. Here is, effectively, the Lisp equivalent, along with the typical Lisp style guidelines:

  (defconstant +logging-enabled+ t)

  (defmacro log-message (message)
    (when +logging-enabled+
         `(err-say ,message)))

  (log-message (crazily-expensive-computation))

Like other structures, they can be abused or used with great success. Based on my limited experience with a number of quicklisp-downloaded packages, I have found macros helpful and unnoticeable as macros.

Irony: Fewer bracing symbols.

In the next blog post, I am hoping to see how perl 6's macro feature handles the parsing of passed-in code. Specifically, I would like to see an example for do-in-reverse:

  (defmacro do-in-reverse (&body commands)
    `(progn ,@(reverse commands)))

  (do-in-reverse
    (princ "First")
    (princ "Second")
    (princ "Third")))

Prints "ThirdSecondFirst"


There isn't yet any API for introspecting ASTs ("parsing of passed-in code" as you call it), nor for programmatically constructing new AST nodes. Such things will hopefully emerge once macro implementation and specification become more concrete.

So I can only guess what it would look like; take the following with a rock of salt:

    macro do-in-reverse($code) {
         $code.clone(statements => $code.statements.reverse);
    }

    do-in-reverse {
        say 'First';
        say 'Second';
        say 'Third';
    };
But it might turn out not be that simple.

The diffulcty comes from the fact that unlike Lisp, in Perl 6 not everything is a list, so you can't treat the AST as a list (... of lists, possibly) either. The .clone would take care to preserve things like outer lexicals and the signature of the block (you don't see it; it's implicit) and other non-listy things.


So potentially not to different to how you might do it in Io (www.iolanguage.com):

    doInReverse := method (
        m     := call argAt(0)
        stmts := list()              // list of statements (ie. messages)
    
        loop (
            rest := m next           // rest of messages after current 
            stmts append(m setNext)  // get current message
            m := rest
            if (m == nil, break)     // exhausted statements when "nil"
        )

        stmts reverseForeach (n, doMessage(n))
    )

    doInReverse( 
        writeln("First") 
        writeln("Second") 
        writeln("Third") 
    )
Of course this is easy in Io because everything is just a message.

NB. The above code doesn't actually amend the AST but it could. Here are some previous examples of amending AST in Io posted here: http://news.ycombinator.com/item?id=1810480 http://news.ycombinator.com/item?id=1804599


I like your proposal, especially if it could be expanded a bit:

  macro do_in_reverse($value, @code) ...


It's honestly not that big of a deal. It sounds much scarier than it is. Typically a generous helping of common sense and thought will deal with the bad cases.




Consider applying for YC's W25 batch! Applications are open till Nov 12.

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: