Beefy Boxes and Bandwidth Generously Provided by pair Networks Cowboy Neal with Hat
"be consistent"
 
PerlMonks  

Comment on

( #3333=superdoc: print w/ replies, xml ) Need Help??
Hello

I believe this is a very interesting and important thing. Macros does give a language more expression power. Perl, in its deepest philosophy, is about giving the programmer the ability to express his/her ideas with the most succecent way, and macroes would do that.

Consider the Switch module by TheDamian. Here is a small snippet from the snippets section in the docs:

use Switch; switch ($val) { case 1 { print "number 1" } case "a" { print "string a" } case [1..10,42] { print "number in list" } case (@array) { print "number in list" } case /\w+/ { print "pattern" } case qr/\w+/ { print "pattern" } case (%hash) { print "entry in hash" } case (\%hash) { print "entry in hash" } case (\&sub) { print "arg to subroutine" } else { print "previous case not true" } }
This implementation of Switch added to the syntax of perl something that wasn't there and was unexpressable in perl. Now Switch was implemented using the low level Filter::Util::Call, and the code doesn't look pretty (but that's not important now as long as it can be done). The problem lies in the fact that you cannot mix two modules that extend the syntax. Imagine mixing Switch with Lingua::Romana::Perligata to get a Latin Switch :-). In Scheme (or Lisp), you can extend the syntax of the language without breaking compatibility with other syntactic modules.

In Scheme, the syntax recognizer/expander works before the code is passed to the actual compiler. The reader expands all macroes and passes them to the compiler that recognizes only ther core operators and functions (See the scheme revised report to see how let can be expressed using a lambda expression or vise versa and how letrec/let* can be expressed in terms of let and set!). Now that's easy to do for lisp, but not impossible to do in perl. To achieve this in perl, first you need a tokenizer that can accept arbitrary possible expressions without regurous checking (should accept "grep map test 'hahaha' and die;") and build the parse tree that is later modifies by the syntax expander. After all syntactical expressions are expanded, the code is passed to the actual perl compiler.

Now back to Switch. If we had a macro system, the implementation of switch would be simple straight forward:

syntax (switch (EXPR) CODE) { # eval the expr first to avoid # reevaluation at each case my $var = new_unique_symbol; code { { $var = EXPR; switch_aux($var) CODE } } } syntax (switch_aux (EXPR) { case CODE_t { CODE_c } CODE_e }) { # else is left as an excercise. code{ if(case(EXPR,CODE_t)){ CODE_c } else { switch_aux(EXPR){ CODE_e } # notice the recursion here } } } syntax (case (EXPR,INTEGER)){ code { (EXPR == INTEGER) } } syntax (case (EXPR,STRING)){ code { (EXPR eq STRING) } } syntax (case (EXPR,LIST)){ code { (grep EXPR, LIST) } } syntax (case (EXPR,REGEX)){ code { (EXPR =~ REGEX ) } } syntax (case (EXPR,HASH)){ code { (exists EXPR, HASH) } } syntax (case (EXPR,SUB)){ code { SUB(EXPR) } }
That was my slightly more than $0.02 worth of comments. Hope it helps,

Update: One more note: Parse::RecDescent would feel more at home if we have such syntax expansion so that instead of passind all the rules and actions as one string, they would be incorporated into perl directly. Example:

parser = new Parse::RecDescent (q{ expression: and_expr '||' expression | and_expr and_expr: not_expr '&&' and_expr | not_expr not_expr: '!' brack_expr | brack_expr brack_expr: '(' expression ')' | identifier identifier: /[a-z]+/i }); # becomes after dropping the quoting operator q{} parser = new Parse::RecDescent( expression: and_expr '||' expression | and_expr and_expr: not_expr '&&' and_expr | not_expr not_expr: '!' brack_expr | brack_expr brack_expr: '(' expression ')' | identifier identifier: /[a-z]+/i );

In reply to Re: A Macro System for Perl? by abstracts
in thread A Macro System for Perl? by samtregar

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post; it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • Outside of code tags, you may need to use entities for some characters:
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.
  • Log In?
    Username:
    Password:

    What's my password?
    Create A New User
    Chatterbox?
    and the web crawler heard nothing...

    How do I use this? | Other CB clients
    Other Users?
    Others imbibing at the Monastery: (6)
    As of 2014-04-19 13:53 GMT
    Sections?
    Information?
    Find Nodes?
    Leftovers?
      Voting Booth?

      April first is:







      Results (480 votes), past polls