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)?
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.
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.
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" ; }
I haven't tried any of these, but if you have the time, you could try
Macro
macro
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.
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.
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 & .
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With