Skip to content

Comment on Macros in Perl6parent

Comments

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) ...
AboutSource Built by g1lg1l

Hackerly is an independent reader for Hacker News, built on the public HN API. Not affiliated with Y Combinator.