如何创建一个接受所有类型变量的子例程(标量,散列,数组或引用)

时间:2014-02-13 06:27:56

标签: perl perl-data-structures

如何创建一个接受所有类型变量的子例程,并确定它是否是(标量,散列,数组或参考)

sub know_var {
    my $this_var = shift;

    if ($this_var eq "array"){
        print "This variable is an array!";
    } elsif ($this_var eq "hash") {
        print "This variable is a hash!";
    } elsif ($this_var eq "hash ref") {
        print "This variable is an hash reference!";
    } so on..

}

my @array = ('foor', 'bar');
my %hash  = (1 => "one", 2 => "two");
my $scalar = 1;
my $scalar_ref = \$scalar;
my $hash_ref = \%hash;
my $arr_ref = \@array;

know_var(@array);
know_var($scalar_ref);
and so on...

我的目标是创建一个类似于Data :: Dumper的子程序, 我的第一个问题是确定要处理的变量类型。

2 个答案:

答案 0 :(得分:6)

来自perlsub

  

函数调用和返回值的Perl模型很简单:所有函数都作为参数传递给一个单独的标量列表,并且所有函数同样返回给它们的调用者一个单独的标量列表。这些调用和返回列表中的任何数组或散列都将崩溃,失去其身份 - 但您可能总是使用pass-by-reference来避免这种情况。

因此,您可以使用引用和ref()来检查引用类型

sub know_var {
  my $this_var = shift;

  if (ref($this_var) eq "ARRAY") { 
    print "This variable is an array reference!";
  }
  elsif (ref($this_var) eq "HASH") { 
    print "This variable is an hash reference!";
  }
  elsif (ref($this_var) eq "SCALAR") { 
    print "This variable is an scalar reference!";
  }
  elsif (!ref($this_var)) { 
    print "This variable is plain scalar!";
  }

}

know_var(\@array);
know_var(\%hash);
know_var(\$scalar);
know_var($scalar);

答案 1 :(得分:1)

本着TIMTOWTDI的精神,为了拉扯我自己的商品,这里有一个替代方案,使用multisubs ......

use v5.14;
use warnings;
use Kavorka qw( multi fun );

multi fun foobar (ArrayRef $x) {
   say "It's an array";
}

multi fun foobar (HashRef $x) {
   say "It's a hash";
}

multi fun foobar (Num $x) {
   say "It's a number: $x";
}

multi fun foobar (Str $x) {
   say "It's a string: $x";
}

foobar( [] );
foobar( {} );
foobar( 1.234 );
foobar( "Hello world" );
foobar( \*STDOUT );  # dies