Home > database >  Can you print the subroutine's argument name in Perl?
Can you print the subroutine's argument name in Perl?

Time:01-20

It's possible to print a variable's name by *var{NAME}, is it possible to print the argument's name in a subroutine?

Below is what I want to achieve

var_name($myVar); will print myVar

sub var_name{
   print *_{NAME};  # Prints `_`, but want `myVar`
}

CodePudding user response:

First, your attempt using print *_{name}; does work; but it prints the name associated with the typeglob of _ (The one for things like $_ and @_), which isn't what you want. If you pass a typeglob/reference to typeglob to the function you can extract its name by de-referencing the argument:

#!/usr/bin/env perl
use warnings;
use strict;
use feature qw/say/;

# The prototype isn't strictly necessary but it makes it harder
# to pass a non-typeglob value.
sub var_name :prototype(\*) {
  say *{$_[0]}{NAME}; # Note the typeglob deref
}

my $myVar = 1;
say *myVar{NAME}; # myVar
var_name *myVar;  # myVar

CodePudding user response:

You get _ because the NAME associated with *_ is _.

So what glob should you use? Well, the glob that contains the variable used as an argument (if any) isn't passed to the sub, so you're out of luck.

A glob-based solution would never work with my variables anyway since these aren't found in globs. This means the very concept of a glob-based varname couldn't possibly work in practice.

Getting the name of the variables would entail examining the opcode tree before the call site. I believe this is how operators achieve this in situations such as the following:

$ perl -we'my $y; my $x = 0   $y;'
Use of uninitialized value $y in addition ( ) at -e line 1.
$ perl -MO=Concise -we'my $y; my $x = 0   $y;'
a  <@> leave[1 ref] vKP/REFC ->(end)
1     <0> enter v ->2
2     <;> nextstate(main 1 -e:1) v:{ ->3
3     <0> padsv[$y:1,3] vM/LVINTRO ->4
4     <;> nextstate(main 2 -e:1) v:{ ->5
9     <2> sassign vKS/2 ->a
7        <2> add[t3] sK/2 ->8                  <-- This is what's issuing
5           <$> const[IV 0] s ->6                  the warning.
6           <0> padsv[$y:1,3] s ->7            <-- This is the source of
8        <0> padsv[$x:2,3] sRM*/LVINTRO ->9        the name in the warning.
-e syntax OK
  •  Tags:  
  • perl
  • Related