in reply to Re^4: Macro in perl code?
in thread Macro in perl code?

sub X() { 0 } print "$message1 \n" if( runtime cond);

Erm, no. The sub and the print statement being on the same line is an artifact of the code being a oneliner :-)

The point is that

sub X() { 0 }

is folded into a constant at compile time (more accurate after compiling - while optimizing), and the resulting constant is used by the optimizer to further reduce the optree throwing away code which, depending on that constant, is never reached.

So, it's not a (runtime cond). You get a mandatory warning if you redefine the constant defining sub X() { } at runtime, and you won't get back code that has been optimized away after compile.

I assumed that since the OP did preprocessing with m4 even before the perl compiler sees the code, the value for his $verbose doesn't change at runtime, but I may be mistaken. Conditional code that depends (or could depend) on runtime state can't be optimized that way, so there's a difference in writing

{ my $debug = 0; if ($debug) { warn "debug set\n"; } }

and

{ sub debug () { 0 } if (debug) { warn "debug set\n"; } }

Only in the latter case the if() block is optimized away, even if, in the former, there's no place in the scope in which the my $debug is declared, where its value would change.

qwurx [shmem] ~ > perl -MO=Deparse,-x,-p { my $debug = 0; if ($debug) { warn "debug set\n"; } } __END__ { (my $debug = 0); if ($debug) { warn("debug set\n"); } } __DATA__ (<Ctrl>D pressed) - syntax OK qwurx [shmem] ~ > perl -MO=Deparse,-x,-p { sub debug () { 0 } if (debug) { warn "debug set\n"; } } __END__ sub debug () { 0 } { '???'; } __DATA__ (<Ctrl>D pressed) - syntax OK

--shmem

_($_=" "x(1<<5)."?\n".q·/)Oo.  G°\        /
                              /\_¯/(q    /
----------------------------  \__(m.====·.(_("always off the crowd"))."·
");sub _{s./.($e="'Itrs `mnsgdq Gdbj O`qkdq")=~y/"-y/#-z/;$e.e && print}

Replies are listed 'Best First'.
Re^6: Macro in perl code?
by Krambambuli (Curate) on Oct 17, 2007 at 09:21 UTC
    Thank you. It took some time, but now [thanks god, finally...! :) ] I got it.

Re^6: Macro in perl code?
by pileofrogs (Priest) on Oct 17, 2007 at 16:01 UTC

    Ah.. no wonder I couldn't make it work...

    I am using a runtime condition. The idea was rather than call a function which evaluates the cond and may simply exit, put the code inline and avoid the function call overhead.

      Uh, sorry. Seems like I've been barking up the wrong tree all the time.

      But! since you wrote

      My script has the global $verbosity which is set by command line args.

      I ask - does this value change ever after? Because if not, you can make that a static via

      BEGIN { my $verbosity = shift; # or Getopts::Std, whatever... eval "sub verbose () { $verbosity }"; }

      of course only after examining under severe scrutiny what $verbosity holds (untaint, perlsec).

      Since the BEGIN block is a separate compile & run, the sub is defined and a constant sub after that, and its value can be used for optimizations. If the values you compare $verbose with are plain numbers as the 1 in

      print "Holy Crap = $holy_crap\n" if $verbose >= 1;

      then optimization should work, because then you have constant vs. constant comparisons. Let's see...

      qwurx [shmem] ~ > perl -MO=Deparse,-x,-p - 1 BEGIN { my $verbose; 1 while ($verbose = shift) !~ /^\d$/; # get rid of -MO=Dep... eval "sub verbose () { $verbose }"; } print "Holy Crap = $holy_crap\n" if verbose >= 1; __END__ sub BEGIN { my($verbose); '???' while (not (($verbose = shift(@ARGV)) =~ /^\d$/)); eval("sub verbose () { $verbose }"); } print("Holy Crap = $holy_crap\n"); __DATA__ - syntax OK qwurx [shmem] ~ > perl -MO=Deparse,-x,-p - 0 BEGIN { my $verbose; 1 while ($verbose = shift) !~ /^\d$/; # get rid of -MO=Dep... eval "sub verbose () { $verbose }"; } print "Holy Crap = $holy_crap\n" if verbose >= 1; __END__ sub BEGIN { my($verbose); '???' while (not (($verbose = shift(@ARGV)) =~ /^\d$/)); eval("sub verbose () { $verbose }"); } '???'; <----- hooray! gone :-) __DATA__ - syntax OK

      bingo :-)

      --shmem

      _($_=" "x(1<<5)."?\n".q·/)Oo.  G°\        /
                                    /\_¯/(q    /
      ----------------------------  \__(m.====·.(_("always off the crowd"))."·
      ");sub _{s./.($e="'Itrs `mnsgdq Gdbj O`qkdq")=~y/"-y/#-z/;$e.e && print}

      It sounds like you have a limited number of conditions (the different levels of verbosity), so you could something like the following:

      use constant MAX_VERBOSITY => 5; sub vprint { # Or whatever. our $msg; local *msg = \($_[0]); print("$msg\n"); } BEGIN { my $verbosity = $ARGV[0] || 0; # Or whatever my $eval = ''; for (1..MAX_VERBOSITY) { $eval .= ($_ <= $verbosity ? "*vprint$_ = \&vprint;\n" : "use constant vprint$_ => 1;\n" ); } eval $eval."1;\n" or die $@; } vprint1("msg1"); # Optimized away if arg is < 1 vprint2("msg2"); # Optimized away if arg is < 2 vprint3("msg3"); # Optimized away if arg is < 3 vprint4("msg4"); # Optimized away if arg is < 4 vprint5("msg5"); # Optimized away if arg is < 5

      Update: Ah woops! There'll be a prototype mismatch. The best you can do (without playing with the opcode tree) is:

      use constant MAX_VERBOSITY => 5; BEGIN { my $verbosity = $ARGV[0] || 0; # Or whatever my $eval = ''; for (1..MAX_VERBOSITY) { my $allow = ($_ <= $verbosity) ? 1 : 0; $eval .= "use constant V$_ => $allow;\n"; } eval $eval."1;\n" or die $@; } sub vprint { # Or whatever. our $msg; local *msg = \($_[0]); print("$msg\n"); } vprint("msg1") if V1; # Optimized away if arg is < 1 vprint("msg2") if V2; # Optimized away if arg is < 2 vprint("msg3") if V3; # Optimized away if arg is < 3 vprint("msg4") if V4; # Optimized away if arg is < 4 vprint("msg5") if V5; # Optimized away if arg is < 5

      Tested

      >perl -MO=Terse 645574.pl 3 LISTOP (0x1986d80) leave [1] OP (0x1986864) enter COP (0x1986da4) nextstate UNOP (0x1986e00) entersub [2] UNOP (0x1986e3c) null [141] OP (0x1986e20) pushmark SVOP (0x1986e60) const [7] PV (0x182ff6c) "msg1" UNOP (0x1986e80) null [17] PADOP (0x1986ea0) gv GV (0x191a7f4) *vprint COP (0x1986c64) nextstate UNOP (0x1986cc0) entersub [4] UNOP (0x1986cfc) null [141] OP (0x1986ce0) pushmark SVOP (0x1986d20) const [8] PV (0x191a7d0) "msg2" UNOP (0x1986d40) null [17] PADOP (0x1986d60) gv GV (0x191a7f4) *vprint COP (0x1986b24) nextstate UNOP (0x1986b80) entersub [6] UNOP (0x1986bbc) null [141] OP (0x1986ba0) pushmark SVOP (0x1986be0) const [9] PV (0x191a7b8) "msg3" UNOP (0x1986c00) null [17] PADOP (0x1986c20) gv GV (0x191a7f4) *vprint COP (0x19869e4) nextstate OP (0x1986a20) null [5] COP (0x19868a4) nextstate OP (0x19868e0) null [5] 645574.pl syntax OK >perl -MO=Terse 645574.pl 3 msg1 msg2 msg3

      I'm betting this is the fastest you'll get.