我们可以将标量或者数组引用强制为Perl中的数组吗?
时间:2020-03-05 18:37:57 来源:igfitidea点击:
我有一个Perl变量$ results从服务返回。该值应该是一个数组,而$ results应该是一个数组引用。但是,当数组中只有一项时,将$ results设置为该值,而不是包含该项的引用数组。
我想对预期的数组做一个" foreach"循环。不检查ref($ results)eq'ARRAY'`,是否有任何等同于以下内容的方法:
foreach my $result (@$results) { # Process $result }
该特定的代码示例将用作参考,但会抱怨简单的标量。
编辑:我应该澄清,没有办法让我更改从服务返回的内容。问题在于,当只有一个值时,该值将为标量;而当存在多个值时,该值将为数组引用。
解决方案
回答
我刚刚用以下方法对此进行了测试:
#!/usr/bin/perl -w use strict; sub testit { my @ret = (); if (shift){ push @ret,1; push @ret,2; push @ret,3; }else{ push @ret,"oneonly"; } return \@ret; } foreach my $r (@{testit(1)}){ print $r." test1\n"; } foreach my $r (@{testit()}){ print $r." test2\n"; }
而且似乎工作正常,所以我认为这与从服务中返回结果有关吗?
如果我们无法控制退货服务,那么可能很难破解
回答
我不确定除了以下以外还有其他方法:
$result = [ $result ] if ref($result) ne 'ARRAY'; foreach .....
回答
我将在循环内重构代码,然后执行
if( ref $results eq 'ARRAY' ){ my_sub($result) for my $result (@$results); }else{ my_sub($results); }
当然,只有在循环中的代码不平凡的情况下,我才会这样做。
回答
另一个解决方案是将调用包装到服务器,并使其始终返回一个数组以简化余生:
sub call_to_service { my $returnValue = service::call(); if (ref($returnValue) eq "ARRAY") { return($returnValue); } else { return( [$returnValue] ); } }
这样,我们始终可以知道我们将返回对数组的引用,即使它只是一项。
foreach my $item (@{call_to_service()}) { ... }
回答
好吧,如果你做不到...
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 }
为了避免这种危险的字符串评估,它变得非常丑陋!
for my $result ( eval { $results->[0] } || $results, eval { @$results[1 .. $#{ $results }] } ) { # Process result }
PS。我的偏好是在reatmon提供的sub ala call_to_service()示例中将其抽象出来。