你可以强制一个标量或数组ref在Perl中作为数组吗?

我有一个从服务返回的perl变量 $ results 。该值应该是一个数组,并且 $ results 应该是一个数组引用。但是,当数组中只有一个项目时, $ results 将被设置为该值,而不是包含该项目的引用数组。

我想在预期的数组上执行一个 foreach 循环。如果不检查 ref($ results)eq'ARRAY',是否有任何方法可以使某些东西等同于以下内容:

foreach my $result (@$results) {
    # Process $result
}

该特定的代码示例将用于参考,但会为简单的标量而抱怨。

编辑:我应该澄清,我没有办法改变从服务返回的内容。问题是,只有一个值时,该值将成为标量,并且当有多个值时,它将成为数组引用。

0
额外 编辑
意见: 3
这种行为让我想大喊一声,就像“愚蠢的PERL!”但后来我意识到,不需要这种废话的语言仍然在引擎盖下进行操作,这使得它稍微麻烦一点....
额外 作者 Rooster,

5 答案

我刚刚测试过这个:

 #!/ usr / bin / perl -w
严格使用;

子测试{

 我的@ret =();
 if(shift){
   push @ ret,1;
   push @ ret,2;
   push @ ret,3;
}其他{
  推@ret,“oneonly”;
}

返回\ @ret;
}

foreach my $ r(@ {testit(1)}){
  打印$ r。“test1 \ n”;
}
foreach my $ r(@ {testit()}){
   打印$ r。“test2 \ n”;
}
</代码> 

它似乎工作正常,所以我认为这与从服务返回结果有关系吗? 如果你无法控制返回的服务,这可能很难解决

0
额外

我不确定除了以下任何其他方式:

  $ result = [$ result] if ref($ result)ne'ARRAY';
foreach .....
</代码> 
0
额外

那么如果你做不到......

for my $result ( ref $results eq 'ARRAY' ? @$results : $results ) {
    # Process result
}

或这个...

for my $result ( ! ref $results ? $results : @$results ) {
    # Process result
}

那么你可能不得不尝试像这样毛茸茸的恐怖!....

for my $result ( eval { @$results }, eval $results ) {
    # Process result
}

并避免危险的字符串的eval变成真难看的fugly!....

for my $result ( eval { $results->[0] } || $results, eval { @$results[1 .. $#{ $results }] } ) {
    # Process result
}

PS。我的选择是在reatmon给出的sub ala call_to_service()例子中将其抽象出来。

0
额外
这不是一个字符串评估。循环(某些涉及@ $结果的表达式)与循环(@ $ results)非常不同。前者将复制数组(消耗内存);后者会替代它(并允许通过循环变量修改元素)。
额外 作者 ysth,
@ysth - 有...请参阅“eval $ results”。我的建议是使用前面给出的call_to_service()示例。我的回答有点像是一个“口齿不清的解决方案”,是由于海报强加的限制,所以很好地指出它的缺陷。
额外 作者 draegtun,

我会重新考虑循环内的代码,然后做

if( ref $results eq 'ARRAY' ){
    my_sub($result) for my $result (@$results);
}else{
    my_sub($results);
}

当然,我只会这样做,如果循环中的代码是不平凡的。

0
额外

另一种解决方案是将调用包装到服务器上,让它始终返回一个数组来简化你的余生。

sub call_to_service
{
    my $returnValue = service::call();

    if (ref($returnValue) eq "ARRAY")
    {
        return($returnValue);
    }
    else
    {
       return( [$returnValue] );
    }
}

然后,你总是可以知道你将返回一个数组的引用,即使它只有一个项目。

foreach my $item (@{call_to_service()})
{
  ...
}
0
额外