【问题标题】:How to check if the first variable passed into a method is a string. Perl如何检查传递给方法的第一个变量是否是字符串。 Perl
【发布时间】:2016-06-28 14:22:02
【问题描述】:

我不知道如何检查这个。如果传入的第一个参数是字符串,我的方法(如果方法中的条件)应该只工作(执行)。我知道如何检查其他类型,但我似乎找不到任何检查字符串的方法。

对于哈希,我会做类似的事情;

if(ref eq 'HASH') {...}

如果有人可以提供一个简单的示例,我相信我可以将它应用到我正在做的事情中。如果需要,我将提供该方法的代码和该方法的整个操作细节的解释。

添加信息

这是一种在软件中处理不同类型错误的方法,这里有 3 种可能的输入格式:

$class->new("error string message")
$class->new("error string message", code => "UNABLE_TO_PING_SWITCH_ERROR")
$class->new("error string message", code => "UNABLE_TO_PING_SWITCH_ERROR", switch_ip => $ip3, timeout => $timeout)
  • 总是会先出现错误信息字符串。

  • 对于第一种情况,还有一个 hashref 指向位于库中的错误哈希结构, 如果单词“code”作为 arg 存在,则此方法 new 将进入模板处理。构造更详细的错误消息的位置。 (我已经有了这个逻辑)。

  • 但我必须添加逻辑,以便将错误消息字符串添加到哈希中,因此输出是一个哈希,而不是字符串。

  • 第二种情况与第一种情况非常相似,其中有参数,例如。 switch_ip ,使用类似的模板处理逻辑插入到字符串中,(也有这个)。

  • 所以我认为第一种和第二种情况可以用相同的方式处理,但我不确定,所以在这个问题中将它们分开。

  • 最后一种情况是错误消息字符串本身,我只是将它插入到一键消息哈希 { message => "error string} 中。

所以毕竟我应该如何检查或划分这些错误案例,目前我对带有代码的案例的想法是将参数转储到哈希中,然后使用类似的东西:

 if(exists($param{code}) { doTemplateProcess()...}

我需要确保首先传入一个字符串。这是我最初的问题。我的任何上下文信息有帮助吗?我希望我没有偏离我的问题的主题,如果是这样,我会提出一个新问题。谢谢。

错误哈希 - 位于 Type.pm

use constant ERROR_CODE => {
     UNABLE_TO_PING_SWITCH_ERROR => {
         category => 'Connection Error:',
         template => 'Could not ping switch %s in %s minutes',
         tt => {template => 'disabled'},
         fatal => 1,
         wiki_page => www.error-solution.com/,
      },
 }

来自 cmets:

这些将像这样在软件的代码中调用

ASC::Builder::Error->new(
    "Phase x this occured because y was happening:",
    code      => UNABLE_TO_PING_SWITCH_ERROR,
    switch_ip => $ip3,
    timeout   => 30,
);

【问题讨论】:

  • 这是一种不好的做法。在 Perl 中,最好不要尝试确定值的类型。你会破坏一些东西。相反,使用不同的方法名称、命名选项、参数数量的差异等。
  • 您实际上想要完成什么?除了检查“它是一个字符串”之外,还有其他方法可以验证您的输入。您可能应该使用其中之一。 (例如,匹配正则表达式可能是一个不错的选择)
  • 每个标量要么是一个字符串,要么可以通过用作字符串而变成一个。说你的方法需要一个字符串并没有真正说明什么。你想确保参数不是参考吗?然后使用ref。想确定不是undef?然后使用defined。如果您试图区分字符串和数字 - 您希望 foo(6) 失败而 foo("6") 成功? - 那么答案是请不要那样做。这很难做到,因为这不是一个好主意。
  • 我一直将条件除以偶数个参数,奇数个参数后跟只有一个参数,但我的导师/顾问说我不应该根据参数的位置。我会向您展示将传递给我的方法的不同输入类型/案例吗?我将编辑我的问题,如果我提供一些上下文可能会更清楚?匹配正则表达式,我还没有看到它是如何工作的,但它可能是一个选项
  • 如果您扩展您正在获得的内容以及您想要完成的内容,我们可能会给出更好的答案。非常正确,您不应该依赖参数的“硬定位”(除非“超过几个”)。稍后传入“键值”以转换为散列效果很好,“只是”迭代类似的对象列表也是如此。

标签: string perl if-statement


【解决方案1】:

把你的特定问题的智慧放在一边,引导 Jeff Foxworthy:

  • 如果你有一个标量但它不是一个引用,你可能有一个字符串。

  • 如果您的非参考标量看起来不像一个数字,它可能是一个字符串。

  • 如果您的非引用标量看起来像一个数字,它仍然可以是一个字符串。

  • 如果您的非引用标量具有不同的字符串和数字值,则它可能是双变量。

您知道您的参数列表就是这样:一个列表。列表是标量值的集合。标量可以是参考,也可以不是参考。我认为您正在寻找非参考案例:

die "You can't do that" if ref $first_argument;

除此之外,您必须做一些更有趣的事情来确定它是否是您想要的那种价值。这也可能意味着您拒绝通过重载等伪装成字符串的对象。

也许您可以将第一个参数作为您传递的键值对的一部分。然后,您可以访问该键以提取值并将其删除,然后再使用剩余的对。

【讨论】:

  • 感谢您的精彩解释,我刚刚意识到没有必要检查字符串。这不是必需的。
【解决方案2】:

您可以轻松地检查错误字符串是简单的标量值还是引用。你可以用ref 来做,但是你必须考虑如果第一个参数不是字符串

你想做什么

您应该按照这些思路在 ASC::Builder::Error 包中编写构造函数

sub new {
    my $class = shift;
    my ($error, %options) = @_;

    die if ref $error;

    bless { string => $error }, $class;
}

这个例子简单地死掉了,所以如果程序被调用的不是简单的字符串或数字作为第一个参数,它就会终止程序

你可以这样称呼它

ASC::Builder::Error->new('error')

ASC::Builder::Error->new(42)

一切都会好起来的。如果你尝试

ASC::Builder::Error->new('message', 'code')

然后你会看到一个警告

Odd number of elements in hash assignment

你可能会让这个警告变得致命

如果还有什么,你应该解释

【讨论】:

  • 我有点遵循你的解决方案,我也意识到我也不必先检查字符串。我确实在哈希分配中得到了奇数个元素,但我已经像这样处理它了。 my $self = delete $options{code}; ,我认为这应该可行。感谢您的帮助。
【解决方案3】:

支持以下所有内容很简单:

  • $class->new("s")
  • $class->new("s", code => "s")
  • $class->new("s", code => "s", switch_ip => "s", timeout => "s")

您只需要以下内容:

sub new {
   my ($class, $msg, %opts) = @_;
   ...
}

您可以检查以下内容以检查被调用者提供的内容:

if (exists($opts{code}))
if (defined($opts{code}))
if ($opts{code})

尽管说将始终提供该字符串,但您现在询问如何检查是否提供了该字符串。因此,您可能正在尝试执行验证而不是多态性。你不应该浪费时间做这件事。

让我们看一下您给出的哈希引用示例。 ref($arg) eq 'HASH' 是错误的。对于某些哈希引用返回 false,并且对于某些类似于哈希引用的事物返回 false。以下是更合适的检查:

eval { %$arg; 1 }

字符串的等价物如下:

eval { "$arg"; 1 }

不幸的是,它总是会返回 true!每个值都可以作为字符串。这意味着您能做的最好的事情就是检查是否提供了任何参数。

use Carp qw( croak );

croak("usage") if !@_;

Perl subs 很少执行参数验证。它不仅棘手,而且价格昂贵。它也提供了很少的好处。错误或缺失的参数通常会在不久之后导致异常或警告。


您可能会看到使用croak("usage") if ref($arg);(或更糟的是die if ref($arg);)的建议,但请记住,这些会导致对超载字符串化(这有点常见)的完美对象的拒绝,并且它们将无法检测ASC::Builder::Error->new(code => ...) 的问题,因为code 产生一个字符串。同样,在 Perl 中执行基于类型的参数验证是一种昂贵且错误的做法。

【讨论】:

  • 好的,但是如何保证先有字符串呢?或者这可能吗?
  • @Paul Russell,好吧,你说“总会有一个错误消息字符串”,所以这是一个相当无用的检查! /// 假设检查点是什么?验证?这很不寻常,但您可以使用croak("usage") if !@_;
猜你喜欢
  • 2018-06-14
  • 2014-05-05
  • 1970-01-01
  • 1970-01-01
  • 2012-08-28
  • 1970-01-01
  • 2020-05-28
  • 1970-01-01
  • 2023-03-24
相关资源
最近更新 更多