-1

它似乎类似于写:

use Const::Fast;
const $xx, 77;
sub test {
    do_something_with( $xx );    
}

或者

sub test {
    state $xx =  77;
    do_something_with( $xx );    
}

完成此任务的更好方法是什么: viaconst或 via state

sub get_ip_country {
    my ($ip_address) = @_;
    my $ip_cc_database = GeoIP2::Database::Reader->new(file => '/etc/project/GeoLite2-Country.mmdb');
    ...
}

UPD
在这个 sub 我没有将指针更改为geoip 数据库,所以它应该是const. 但是我不想每次调用 sub 时都重新创建对象(这很慢)。所以我想它会更快使用state,尽管指针没有改变。

好像应该是const state $ip_cc_database

4

3 回答 3

8

他们不做同样的事情。

  • state声明一个变量,它只会在你第一次进入函数时被初始化。虽然它是可变的,所以你可以改变它的值,但它会在调用同一个函数之间保持这个值。该程序将例如打印7879
    sub test {
        state $xx = 77;     # initialization only happens once
        print ++$xx . "\n"; # step the current value and print it
    }
    test; # 78
    test; # 79
    
  • const声明一个不可变(只读)变量,如果在函数中声明,则每次调用函数时都会重新初始化。
于 2022-01-24T13:17:13.847 回答
4

如果你想要一个恒定的值,那么你应该使用类似Const::Fast的东西。

但是,如果您想要一个可以更改的值,但在调用函数之间保留其值,那么您需要一个状态变量

所以运行,这个:

sub test {
  state $x = 1;

  say $x++;
}

test() for 1 .. 10;

给出了这个:

1
2
3
4
5
6
7
8
9
10

但是运行这个:

use Const::Fast;

sub test {
  const my $x, 1;

  say $x++;
}

test() for 1 .. 10;

给出运行时错误:

Modification of a read-only value attempted at const_test line 12.
于 2022-01-24T15:17:47.733 回答
1

正如@TedLyngmo 在对您的 OP 的评论中指出的那样,const statePerl 无效。 const是一个编译指示,所以在编译时工作,state而是一个运行时构造。

就您的效率要求而言,GeoIP2::Database::Reader构造函数只被调用一次,两者都可以。如果您进一步希望它是只读的,这样您就不会无意中使引用无效,您仍然可以同时使用两者。 const自动为您执行此操作,但您可以使用state间接层复制该行为:

sub ip_cc_database {
   state $db = GeoIP2::Database::Reader->new(file => '/etc/project/GeoLite2-Country.mmdb');
}
sub get_ip_country {
    my ($ip_address) = @_;
    my $ip_cc_database = ip_cc_database();
    ...
}

关于何时使用一个而不是另一个的问题的答案有点微妙。

这两种方法的真正区别在于调用构造函数的时间。const在编译阶段使用它,在state运行时使用它。

如果您的应用程序总是调用get_ip_country,并且您不关心在流程的生命周期内摊销启动成本,那就const更简单了。

但是,如果您不总是调用get_ip_country,并且创建GeoIP2::Database::Reader对象的成本很高,那么使用state意味着您只需在需要时支付该成本。

还需要考虑用户体验。如果您的程序是交互式的,或者如果它在您需要调用之前开始生成输出get_ip_country,则延迟创建对象直到它真正需要它意味着您的程序不会只是坐在那里看似什么都不做,直到所有的启动完成。

于 2022-01-25T15:34:21.557 回答