【问题标题】:How to check if a function parameter is a string in perl如何检查函数参数是否是perl中的字符串
【发布时间】:2017-05-29 13:29:15
【问题描述】:

我正在尝试使用 perl 编写我的自定义 validateParameter 函数。 实际上我有以下代码也有效:

sub validateParameter {
    my ($args, $list) = @_;

    if ( ref($list) eq "ARRAY" ) {

        foreach my $key (@$list) {
            if ( not defined $args->{$key} ) {
                die "no $key given!";
            }
        }
    } 
    #elsif ( check if string ) {
    #}
}

我想通过以下方式调用我的函数:

validateParameter({ hallo => "Welt", test => "Blup"},  ["hallo", "test"]);

但我也想这样调用我的函数:

validateParameter({ hallo => "Welt", test => "Blup"},  "hallo");

如何检查给定的 arg 是否为“字符串”?

我知道 perl 只有以下三种数据类型(标量、散列、数组)。但也许有一个聪明的方法来检查一个变量是否是一个字符串。

谢谢大家。

【问题讨论】:

  • 您的意思是“字符串”而不是“数字”吗?还是“字符串”而不是“arrayref/hashref/...”?然后ref 是要走的路(就像你已经做过的那样)。它为简单的非引用标量返回一个空字符串(比如你的$list)。
  • 哦,好吧,我的错:D。这个帖子完成了。谢谢@PerlDuck

标签: function perl arguments subroutine


【解决方案1】:

更新:我不知何故错过了问题的结尾。只是测试ref($list) eq 'ARRAY' 大部分时间都可以工作,但要正确允许重载对象,您应该尝试取消引用参数:

if ( eval { \@$list } ) {
    # it was an array 
}
else {
    # assume it is a string
}

原答案:

您可以检查有关参数的许多内容:

if ( ! defined $param ) {
    # undefined
}
elsif ( defined Scalar::Util::blessed($param) ) {
    # object
}
elsif ( ref $param ) {
    # reference (return of ref will give the type)
}
elsif ( length do { no warnings "numeric"; $param & '' } ) {
    # number
}
else {
    # string
}

但是所有这些(可能除了定义的检查)都违背了 Perl 自动转换为所需类型的目的,并且会限制可以传递的内容(例如,需要数字的字符串或双变量,或需要字符串、数字或引用的重载对象,或绑定变量或魔术变量,例如$!)。

您可能还想看看Params::Validate 可以做什么。

【讨论】:

  • 注意:\@$list 将自动激活$list,如果它是undef,所以如果这是一个有效的输入,那么首先处理undef
  • @ikegami 我猜 undef 更像是一个空数组而不是 undef“字符串”
【解决方案2】:

不,没有办法检查标量是否为字符串,因为 Perl 会根据上下文进行隐式类型转换。如果您将数字作为函数的第二个参数,并且在需要字符串的上下文中使用它,它将自动转换为字符串。因此,只需检查 ref($list) 是否为空 - 在这种情况下,$list 不是引用,因此它是字符串或数字,您无需区分这两者。

【讨论】:

  • 嗯,有Scalar::Util::looks_like_number(核心模块)来检测数字,但我认为这不是OP所追求的。
  • 请注意,ref($list) 将为字符串化重载的对象返回 true。这意味着如果您使用ref ,即使$url 可以用作字符串,my $url = URI->new('http://stackoverflow.com/'); validateParameter({ hallo => "Welt", test => "Blup"}, $url); 也会失败。
【解决方案3】:

不要将行为基于参数的“类型”,因为真的不存在这样的事情。如果你使用基于类型的多态,你会遇到问题,因为 Perl 的值通常有不止一种类型。

例如,

  • "123" 产生的标量存储为字符串,但 Perl 并没有将它与123 产生的标量区分开来,后者不存储为字符串。

  • 标量可以包含数字和该数字的缓存字符串化。 (例如my $i = 123; "".$i;

  • 标量可以同时包含数字和字符串(这不是数字的字符串化)。常见的例子有$!!1

  • 对重载字符串化的对象的引用也是一个有用的字符串。 (例如DateTime->now

  • 对数组的引用可能会使%{} 重载以用作哈希引用。对哈希的引用可能会使@{} 重载以用作数组引用。

  • 还有更多。

【讨论】:

    猜你喜欢
    • 2011-05-23
    • 2021-04-13
    • 2023-01-29
    • 2012-03-27
    • 1970-01-01
    • 2020-07-13
    • 2015-12-05
    • 1970-01-01
    相关资源
    最近更新 更多