我试图在每个循环中定义一个内联哈希,我的程序不会抛出任何错误但也不会执行print语句.是否可以定义内联哈希,如下所示:
while (my (key, value) = each %{ (apple => "red", orange => "orange", grape => "purple")}) {
print "something";
}
Run Code Online (Sandbox Code Playgroud)
或者我不能在每个循环工作时,如果我直接调用每个返回如下所示的散列的语句中的sub:
sub returnsHash {
my %fruits = (
apple => "red",
orange => "orange",
grape => "purple",
);
return %fruits;
}
while (my (key, value) = each %{ returnsHash() }) {
print "something";
}
Run Code Online (Sandbox Code Playgroud)
ike*_*ami 11
标量上下文中的列表/逗号运算符求值为标量上下文中计算的最后一项的结果.这意味着
each %{ apple => "red", orange => "orange", grape => "purple" }
Run Code Online (Sandbox Code Playgroud)
相当于
each %{ "purple" }
Run Code Online (Sandbox Code Playgroud)
这就是你的两个片段正在做的事情,但它是不受欢迎的,这是一个严格的违规行为.(总是使用use strict; use warnings qw( all );!!!)
您正在使用散列取消引用(%{ ... }),但您没有散列,更不用说您可以取消引用的散列的引用.要构建哈希并返回对哈希的引用,请使用{ ... }.
each %{ { apple => "red", orange => "orange", grape => "purple" } }
Run Code Online (Sandbox Code Playgroud)
虽然这解决了一个问题,但只是揭示了另一个问题:你得到一个无限循环.
迭代器由哈希使用each,keys并values与哈希关联,而不是运算符.由于每次循环都在创建一个新的哈希,因此每次循环都会创建一个新的迭代器,因此您将始终获得新创建的哈希的第一个元素,并且您的循环将永远不会结束.
由于您不需要按键查找项目,因此我不明白为什么您要使用哈希.您可以使用以下代码:
for (
[ apple => "red" ],
[ orange => "orange" ],
[ grape => "purple" ],
) {
my ($key, $val) = @$_;
...
}
Run Code Online (Sandbox Code Playgroud)
如果你从sub获得列表,以下是你如何编写上面的内容.
use List::Util qw( pairs );
for (pairs(f())) {
my ($key, $val) = @$_;
...
}
Run Code Online (Sandbox Code Playgroud)
但是,这两个都创建了许多数组.由于没有破坏性的问题,我会使用以下方法来避免这个问题:
{
my @kvs = f();
while ( my ($key, $val) = splice(@kvs, 0, 2) ) {
...
}
}
Run Code Online (Sandbox Code Playgroud)
您也可以使用以下内容,但我认为很多人会对此感到困惑:
for (
my @kvs = f();
my ($key, $val) = splice(@kvs, 0, 2);
) {
...
}
Run Code Online (Sandbox Code Playgroud)
这是不可能的,因为每个只能按预期使用实际变量,散列或数组.请参阅文档中的概要.这同样适用于键和值.
第二次尝试也是如此,其中函数在每次迭代中也被重新调用.
请注意,尝试的一个明智的事情是%{ {...} }(而不是%{ (...) })因为内部的东西%{}必须是哈希引用.这适用于两个尝试,因为函数返回一个哈希值,从而返回一个标量列表.(根据第一个声明,这仍然无济于事.)
我不确定需要什么,因为哈希可以在循环之前定义.此外,我建议each在使用之前仔细查看,因为它带有复杂性.
我认为你想要迭代动态创建的这类对的列表的键值对.这是一种使用自定义迭代器(包装所使用的哈希迭代器each)的方法
use warnings;
use strict;
use feature 'say';
my $hit = get_each_it(a => 1, b => 2, c => 3);
while (my ($k, $v) = $hit->()) {
say "$k => $v";
}
my ($k, $v) = $hit->(); # restarts the iterator
say "$k --> $v";
($k, $v) = $hit->(); # next (keeps state)
say "$k --> $v";
sub get_each_it {
my %h = @_;
return sub { return each %h }
}
Run Code Online (Sandbox Code Playgroud)
重复和继续迭代(在散列耗尽或单个调用之后)是每个使用的散列迭代器的基本属性,并且在执行此操作时
只要给定的散列未经修改,您就可以依赖
keys,values并each重复返回相同的顺序.
请仔细研究这是如何工作的.
有关迭代器的详细信息,请参阅Perl.com上的这篇文章.迭代器的详细讨论在Iterator模块中给出,并附有教程.我不太清楚这个模块,但是文档值得一读; 每一个警告和警告都适用each.
如果在哈希耗尽后你不需要(或想要)重置迭代器以继续迭代的能力,这里是使用splice的ikegami注释的替代迭代器
sub get_each_it {
my @kv = @_;
return sub { return splice @kv, 0, 2 }
}
Run Code Online (Sandbox Code Playgroud)
这不会被纠缠在一起each,它也会按提交列表的顺序进行迭代.
请注意,通过闭包的属性,生成器返回的每个代码引用仍保留其自己的迭代器,该迭代器在从各种代码段调用时保持其状态.小心使用.