【问题标题】:Pass hash by reference to subroutine w/o using "\": my_subroutine(%my_hash)使用“\”通过引用子程序来传递哈希:my_subroutine(%my_hash)
【发布时间】:2017-02-11 03:14:26
【问题描述】:

如何在不使用 \ 字符的子例程调用表达式(如 my_subroutine(%my_hash))中通过引用子例程来传递哈希?


更多解释(以防前面的单行问题描述性不够)

通过引用子程序传递变量而不使用\ 字符在像my_subroutine($my_var) 这样的子程序调用表达式中可以通过这样定义子程序来实现:

sub my_subroutine {
    my $var_ref = \shift;
    ...
}

我已经尝试过使用哈希的相同方法,但它不能正常工作:

sub my_subroutine {
    my $hash_ref = \shift;
    ...
}

我认为这是因为 perl 将任何传入的散列键值对分段到列表(一维数组)中,即@_,对传入的数组也是如此(但仅对于不使用的值)键)。

我正在寻找一种解决方法,以使my_subroutine(%my_hash) 通过引用传递哈希,而无需在每次调用子例程时都在我的子例程参数(哈希)前面加上反斜杠字符\。这将有助于使我的主代码看起来更整洁,并让不整洁的部分留给子例程的内部。此外,如果我与一大群开发人员一起工作,有人可能会忘记添加引用字符。我需要在子例程中设置它(哈希总是通过引用 my_subroutine 传递),而不是由调用 my_subroutine 的其他开发人员来设置。

【问题讨论】:

  • Re "我认为那是因为...",唯一可以传递给 subs(并从 subs 返回)的是一些标量。执行my_subroutine(%my_hash) 时传递的标量由键的副本和哈希的(实际非副本)值组成。 (原型会影响传递哪些标量。)
  • Re "通过引用子程序传递变量而不使用\ 字符...",Perl 中的变量总是passed by reference(这就是为什么@ 987654333@可以给你参考)。在调用方使用\ 传递a 引用(当然,这是通过引用传递)。
  • “这将有助于使我的主要代码看起来更整洁” 它还会误导实际发生的事情。如果这是你唯一的目标,那就忘掉它吧。

标签: perl


【解决方案1】:

Prototypes may still considered bad,但您可以在这里使用它们来实现您的目标。

sub my_subroutine (\%) {
    my $hashref = shift;
    ...
}

my_subroutine(%hash);

使用原型,子例程的第一个参数被强制为哈希引用。

请注意,在子例程中,哈希作为哈希引用被接收。您还需要使用命名散列调用子例程。

my_subroutine( { "anonymous" => "hash", "not" => "OK" } );  # not OK with proto

【讨论】:

  • 看看优秀的汤姆克里斯蒂安森的Prototypes Considered Harmful。我认为暗示可能是初学者的 OP 可以使用原型子例程,这样他们就不必在调用参数中添加反斜杠,这会适得其反。
【解决方案2】:

这样的事情怎么样:

#!/usr/bin/perl
use warnings;
use strict;
use Data::Printer;

my %h1 = ( a => 10, b => 20);
mySub(%h1);

sub mySub {
    my ($h1) = {@_};
    p $h1;
}

【讨论】:

  • 出了点问题。它不支持编辑传入的哈希。请检查我的测试代码here
  • @Omar 那是因为{@_}@_ 的内容复制到一个新的匿名哈希中。您将无法使用这种方法修改原始哈希。
  • 在这种情况下,您必须使用原型(并确保子在使用之前定义)。请检查对您的要点的回复
  • Gist 将 sub mySub(\%) 显示为 sub mySub(%)。请立即检查。
猜你喜欢
  • 1970-01-01
  • 2014-12-18
  • 2021-10-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-06-14
  • 1970-01-01
相关资源
最近更新 更多