Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I inline Perl subroutines?

I am reading Code Complete 2, and one of the points mentioned is about creating subroutines even for operations that seem too simple to have their own subroutines, and how that can be helpful.

I know I can inline functions in C and C++ using the inline keyword. But I never came across a way to inline subroutines in Perl.

Is there a way to tell the Perl interpreter to inline the subroutine calls (or why not)?

like image 534
Lazer Avatar asked Nov 02 '10 11:11

Lazer


People also ask

How do I run a subroutine in Perl?

If you have subroutines defined in another file, you can load them in your program by using the use , do or require statement. A Perl subroutine can be generated at run-time by using the eval() function. You can call a subroutine directly or indirectly via a reference, a variable or an object.

How can you call a subroutine and identify a subroutine in Perl?

To call subroutines: NAME(LIST); # & is optional with parentheses. NAME LIST; # Parentheses optional if predeclared/imported. &NAME(LIST); # Circumvent prototypes. &NAME; # Makes current @_ visible to called subroutine.

Which keyword is used to define subroutine in Perl?

Defining a Subroutine To define your own subroutine, use the keyword sub , the name of the subroutine (without the ampersand), then the block of code in curly braces which makes up the body of the subroutine. Something like this: sub marine { $n += 1 ; # Global variable $n print "Hello, sailor number $n!\n" ; }


3 Answers

I haven't tried any of these, but if you have the time, you could try

  1. Macro
  2. macro
  3. or even Filter::Macro

They're all source filters so you'll have to check your return on investment in performance. The last actually has a review on cpanratings. (Ignore Dan Dascalescu's attempt to regulate the Perl module "airspace".)

-- Actually, the last one Filter::Macro uses Filter::Simple::Compile (which in turn uses Module::Compile) to compile the routines, so this might perform above the other source filter methods. But the standard caveats on source filters apply.

like image 119
Axeman Avatar answered Oct 14 '22 03:10

Axeman


Constant subroutines, i.e. subroutines with an empty prototype and constant return value, are inline. That is how the constant pragma defines constants:

sub five() { 5 }

would be inlined if it is seen before its first use.

Otherwise, Perl allows subroutines to be dynamically redefined at run time, so inlining is not suitable.

For subroutines that always return the same value given the same inputs, you can use memoization.

Chapter 13 of Programming Perl provides some information on the optimization steps taken by perl.

This is called constant folding. Constant folding isn't limited to simple cases such as turning 2**10 into 1024 at compile time. It also resolves function calls -- both built-ins and user-declared subroutines that meet the criteria from the section "Inlining Constant Functions" in Chapter 6, Subroutines. Reminiscent of FORTRAN compilers' notorious knowledge of their own intrinsic functions, Perl also knows which of its own built-ins to call during compilation. That's why if you try to take the log of 0.0 or the sqrt of a negative constant, you'll incur a compilation error, not a run-time error, and the interpreter is never run at all.

See also perldoc perlguts.

You can see the effect of constant-folding yourself:

#!/usr/bin/perl

use strict; use warnings;

sub log_ok () { 1 }

if ( log_ok ) {
    warn "log ok\n";
}
perl -MO=Deparse t.pl

Output:

sub log_ok () { 1 }
use warnings;
use strict 'refs';
do {
    warn "log ok\n"
};
t.pl syntax OK

Here, constant folding led to the replacement of the if block with a do block because the compiler knew that log_ok would always return a true value. On the other hand, with:

#!/usr/bin/perl

use strict; use warnings;

sub log_ok () { 0.5 > rand }

if ( log_ok ) {
    warn "log ok\n";
}

Deparse output:

sub log_ok () {
    use warnings;
    use strict 'refs';
    0.5 > rand;
}
use warnings;
use strict 'refs';
if (log_ok) {
    warn "log ok\n";
}
t.pl syntax OK

A C compiler might have replaced the if (log_ok) with if ( 0.5 > rand ). perl does not do that.

like image 28
Sinan Ünür Avatar answered Oct 14 '22 03:10

Sinan Ünür


Perl only allows to inline constant functions. From perldoc perlsub:

Functions with a prototype of () are potential candidates for inlining. If the result after optimization and constant folding is either a constant or a lexically-scoped scalar which has no other references, then it will be used in place of function calls made without & .

like image 42
Eugene Yarmash Avatar answered Oct 14 '22 02:10

Eugene Yarmash