我有一个标量,可能是也可能不是对数组的引用。如果它是对数组的引用,我想取消引用它并迭代它。如果没有,我想将它视为一个单元素数组并迭代它。
my $result = my_complicated_expression;
for my $value (ref($result) eq 'ARRAY' ? @$result : ($result)) {
# Do work with $value
}
目前,我有上面的代码,工作正常,但感觉笨重,而不是非常Perlish。如果值不是我期望的值,是否有更简洁的方式来表达使用回退行为取消引用值的想法?
答案 0 :(得分:4)
只需在循环之前强制它。
my $result = *some function call* // [];
$result = [$result] if ref $result ne 'ARRAY';
for my $val ( @$result ){
print $val;
}
#!/usr/bin/perl
use 5.012;
use strict;
no warnings;
sub array_ref;
my $result = [qw/foo bar foobar/];
# $result = 'foo'; # scalar test case
# $result = {foo=>q{bar}}; # hash test case
$result = array_ref $result;
for my $val ( @$result ){
say $val;
}
sub array_ref {
my $ref = shift;
given(ref $ref){
$ref = [%$ref] when('HASH');
$ref = [$ref] when(['SCALAR','']);
when('ARRAY'){}
default {
die 'Did not prepare for other ref types';
}
}
return $ref;
}
这是出于演示目的(您不应该在生产代码中使用given / when),但是显示您可以轻松地测试ref类型并转换新响应。但是,如果你真的不知道你的函数返回什么类型的变量,你怎么肯定它甚至是一个参考。如果是数组或散列怎么办?
答案 1 :(得分:3)
作为perl,对于'对'将会有几个答案。一个是品味问题 - 恕我直言,一个可接受的缩短涉及依赖于the ref function returns the empty string如果给出它的表达式是标量的事实。这意味着如果您知道只有两种可能性(即标量值和数组引用),则您不需要eq 'ARRAY'
。
其次,您可以迭代单个标量值(显然产生1次迭代),因此您不必将$result
括号放在"标量"情况下。
将这两个小的简化用于给予;
use v5.12;
my $result1 = "Hello World";
my $result2 = [ "Hello" , "World" ];
for my $result ($result1, $result2) {
for my $value ( ref $result ? @$result : $result) {
say $value ;
}
}
产生;
Hello World
Hello
World
可能会有更多爱好者。你可以做的事情,但这似乎是简洁和可读之间的合理妥协。当然,YMMV。
答案 2 :(得分:1)
我看到我迟到了,但我无法帮助它。使用eval
和$@
以及逗号运算符
my $ra = [ qw(a b c) ];
my $x = 23;
my $var = $ra;
# my $var = $x; # swap comment to test the other
foreach my $el ( eval { @{$var} }, $@ && $var )
{
next if $el =~ /^$/; # when @$var is good comma adds empty line
print $el, "\n";
}
打印a b c
(每行一个),如果我们切换到my $var = $x
,则会打印23
。
当$var
有引用时,$@
为空,但逗号仍然执行,这会在循环中添加一个空行,即next
。作为跳过空行的替代方法,可以将其过滤掉
foreach my $el ( grep { !/^$/ } eval { @{$var} }, $@ && $var )
此外,还可清除空行。但是,大部分时间都是可取的。
答案 3 :(得分:-1)
sub deref {
map ref($_) eq 'ARRAY'? @$_ : ref($_) eq 'HASH'? %$_ : $_, @_
}
sub myCompExpr {
1, 2, 3, [4, 5, 6], {Hello => 'world', Answer => 42}
}
print $_ for deref myCompExpr