Perl:调度哈希值和共享变量
我有一个模块,其中包含一组函数,这些函数被实现为带有辅助函数的调度哈希,因此:
my $functions = {
'f1' => sub {
my %args = @_;
## process data ...
return $answer;
},
[etc.]
};
sub do_function {
my $fn = shift;
return $functions->{$fn}(@_);
}
这被一些处理制表符分隔数据的脚本使用;正在检查的列由适当的子程序转换。当处理列中的值时,我将数据的哈希值传递给子函数,它会生成一个标量,即该列的新值。
目前,子程序是这样调用的:
my $new_value = do_function( 'f1', data => $data, errs => $errs );
并且参数中的变量都声明为“my” - my $data、my $errs 等。是否可以更新传递到子程序的参数中的其他值而无需归还它们?即不必这样做:
... in $functions->{f1}:
my %args = @_;
## process data ...
## alter $args{errs}
$args{errs}->{type_one_error}++;
## ...
return { answer => $answer, errs => $args{errs} };
...
## call the function, get the response, update the errs
my $return_data = do_function( 'f1', data => $data, errs => $errs );
my $new_value = $return_data->{answer};
$errs = $return_data->{errs}; ## this has been altered by sub 'f1'
我可以这样做:
my $new_value = do_function( 'f1', data => $data, errs => $errs );
## no need to update $errs, it has been magically updated already!
I have a module with a set of functions implemented as a dispatch hash with a helper function thus:
my $functions = {
'f1' => sub {
my %args = @_;
## process data ...
return $answer;
},
[etc.]
};
sub do_function {
my $fn = shift;
return $functions->{$fn}(@_);
}
This is used by some scripts that process tab-delimited data; the column being examined is converted by the appropriate subroutine. When processing a value in a column, I pass a hash of data to the sub, and it generates a scalar, the new value for the column.
Currently the subs are called thus:
my $new_value = do_function( 'f1', data => $data, errs => $errs );
and the variables in the arguments are all declared as 'my' - my $data, my $errs, etc.. Is it possible to update other values in the arguments that are passed into the subs without having to return them? i.e. instead of having to do this:
... in $functions->{f1}:
my %args = @_;
## process data ...
## alter $args{errs}
$args{errs}->{type_one_error}++;
## ...
return { answer => $answer, errs => $args{errs} };
...
## call the function, get the response, update the errs
my $return_data = do_function( 'f1', data => $data, errs => $errs );
my $new_value = $return_data->{answer};
$errs = $return_data->{errs}; ## this has been altered by sub 'f1'
I could do this:
my $new_value = do_function( 'f1', data => $data, errs => $errs );
## no need to update $errs, it has been magically updated already!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
您可以传递对值的引用并在子例程内更新它。
例如:
据我从您的代码片段中看到,
$errs
已经引用了哈希。所以,实际上,您所要做的就是 - 只需注释掉行
$errs = $return_data->{errs};
并尝试如果我得到了正确的代码,
$errs
已更新。然后您应该将返回值更改为$answer
并执行以下操作:You can pass reference to value and update it inside of subroutine.
For example:
And as far as I can see from your code snippets,
$errs
is already reference to hash.So, actually, all you have to do - just comment out line
$errs = $return_data->{errs};
and tryIf I get your code right,
$errs
gets updated. And then you should just change your return value to$answer
and do:首先将
do_function
的定义更改为:这是分派到新子例程的正确方法。这种形式的
goto
用新的 coderef 替换当前正在执行的子例程,不变地传递@_
,并从调用堆栈中删除do_function
(因此 <代码>调用者工作正常)。您可能还需要在其中进行一些错误检查,以确保$fn
是一个有效的名称。在你的函数中,你可以直接修改
@_
的单元格,并且不需要通过引用传递任何内容(因为perl已经为你做到了这一点)。支持
key => value
参数而不通过引用传递,你可以这样写:HOWEVER 因为在您的情况下
$errs
是一个哈希引用,您不需要需要做任何额外的工作。所有引用都会自动通过引用传递。在现有代码中,您所要做的就是修改$args{errs}
的键(正如您现在所做的那样),它将修改对该哈希的每个引用。如果您想要函数本地哈希,则需要复制哈希*:
其中
%errs
是私有的,完成后,您可以使用$ 将您想要公开的任何值推送到
。但请确保不要将$args{errs}
中args{errs}{...} = ...;$args{errs}
替换为副本(如$args{errs} = \%errs
),因为这会中断与调用者的连接错误哈希。如果您想复制所有新值,可以使用以下之一:*或本地化部分/全部键
first change your definition of
do_function
to:that is the proper way to dispatch to a new subroutine. this form of
goto
replaces the currently executing subroutine with the new coderef, passing@_
unchanged, and removingdo_function
from the call stack (socaller
works right). you probably want some error checking in there too, to make sure that$fn
is a valid name.inside your function, you can simply modify cells of
@_
directly, and you do not need to pass anything by reference (since perl already did that for you).to support
key => value
arguments without passing by reference you could write it this way:HOWEVER since in your case
$errs
is a hash reference, you don't need to do any extra work. all references are passed by reference automatically. in your existing code, all you have to do is modify a key of$args{errs}
(as you are doing right now) and it will modify every reference to that hash.if you wanted a function local hash, you need to make a copy of the hash*:
where
%errs
is private, and once you are done, you can push any values you want to make public into$args{errs}
with$args{errs}{...} = ...;
. but be sure not to replace$args{errs}
with the copy (as in$args{errs} = \%errs
) since that will break the connection to the caller's error hash. if you want to copy all the new values in, you could use one of:*or localize some/all of the keys