0

I want to pass the arguments of my routine to a subroutine as they are, possibly while adding a new argument. To give an example imagine something like this

sub log($$$){
   my ($message, $log_location, $log_level) = @_;
   #logs message
}

sub log_debug($$){
   my ($message, $log_location) = @_;
   log($message, $log_location, DEBUG_LOG_LEVEL);
}

That syntax works fine above, but requires my saving the @_ to intermediate variables to do it. I'm wondering if there is a simple clean syntax for doing so without using the intermediate variables. Something like

log(@_, DEBUG_LOG_LEVEL);

which gets an error about my "not having enough variables", but I think would otherwise work. Can this be done easily without warning?

dsollen
  • 6,046
  • 6
  • 43
  • 84

3 Answers3

3

Sure, just skip the prototypes

sub log {
   my ($message, $log_location, $log_level) = @_;
   #logs message
}

sub log_debug {
   log(@_, DEBUG_LOG_LEVEL);
}
mpapec
  • 50,217
  • 8
  • 67
  • 127
3

You don't have to copy the elements of @_. You could use them directly as follows:

sub log_debug($$) {
    log($_[0], $_[1], DEBUG_LOG_LEVEL);
}

Prefixing the call with & causes the prototype to be ignored, so you could also use the following:

sub log_debug($$) {
    &log(@_, DEBUG_LOG_LEVEL);
}

If you eliminate the arguments (including ()), the callee will use the parent's @_ instead of creating a new one. This following is slightly more efficient than the previous solution:

sub log_debug($$) {
    push @_, DEBUG_LOG_LEVEL;
    &log;
}

Finally, if log obtains a stack trace, you might want to remove log_debug from the trace. This is slightly less efficient.

sub log_debug($$) {
    push @_, DEBUG_LOG_LEVEL;
    goto &log;
}

Note that none of four solutions I posted make a copy of the arguments.

ikegami
  • 367,544
  • 15
  • 269
  • 518
1

You can skip prototype checking by calling your subroutine with an &:

&log(@_, DEBUG_LOG_LEVEL);

According to perlsub:

Not only does the & form make the argument list optional, it also disables any prototype checking on arguments you do provide. This is partly for historical reasons, and partly for having a convenient way to cheat if you know what you're doing.

Matt Jacob
  • 6,503
  • 2
  • 24
  • 27