2

In perl there is the shift function that can act on the @_(arguments of a function in scope of which it was called) if no arguments supplied.

Can I write a custom function in perl with the same behavior(some kind of my_shift)?

I tried this:

use Data::Dumper;

sub get_caller_args (;$) {
  my $n = shift;
  $n = defined $n? $n:1;
  my $ret;
  package DB {
    my($t,$t1) = caller($n);
  };
  $ret = \@DB::args;
  return $ret;
}

sub test ($@) {
  my $self = shift;
  print "Self: $self.\n";
  print Dumper(get_caller_args()), "\n";
}

It kind of works, but

test(1,2,3)

outputs:

Self: 1.
$VAR1 = [
          1,
          2,
          3
        ];

So it doesn't see changes made by shift (though it can see changes made by pop).

But I want it to act like this:

sub test {
  my $self = shift;
  print my_function;
}

Here the my_function called without arguments must act on the @_, in this case on the rest of the arguments, without the first as it was shifted(actually I need only to read arguments, not to do changes).

Bad_ptr
  • 593
  • 3
  • 15
  • @martinclayton I tested it with perl v5.18.2, and it works for me). The problem is to write a function that can access the calling function arguments, like shift does(however I do not need to change the arguments, only to read). Is it possible? (it is not a very practical problem, of course) – Bad_ptr Mar 02 '15 at 08:47
  • 1
    Not without a call checker or other comparable messing with internals. – ikegami Mar 02 '15 at 10:51
  • 1
    I'd be wondering what you're trying to accomplish. This isn't necessarily a good solution to most problems. – Sobrique Mar 02 '15 at 11:00
  • 1
    http://stackoverflow.com/questions/1347396/when-should-i-use-the-to-call-a-perl-subroutine – Sobrique Mar 02 '15 at 11:02
  • @ikegami: Nonsense. This is exactly what the `&subroutine` call does. – Borodin Mar 02 '15 at 23:05
  • @Borordin, `subroutine(@_)`, `subroutine(\@_)` and `&subroutine` don't cause calls to `subroutine` to default to using `@_`; it's being explicit about it. If you want to default to be `@_` (like `shift`), you need a call checker or some other comparable use of the Perl API or internals. – ikegami Mar 03 '15 at 14:14

1 Answers1

1

Ok, I found an answer:

use feature 'say';

sub my_shift {
 say "Arguments before shift: ", @_;
 shift;
 say "Arguments after shift: ", @_;
}

sub test {
 say "Arguments before my_shift: ", @_;
 &my_shift;
 say "Arguments after my_shift: ", @_;
}

The 'tricky' thing here is to call the my_shift with an ampersand(&) before the function name -- then the function gets arguments of the calling function as it's input.

However I'll not accept this self-answer, because I'm still interested if it possible to do this without that ampersand magic and what if i need to pass other arguments and access the calling function arguments at the same time, etc.

Bad_ptr
  • 593
  • 3
  • 15