1; foreac-6ren">
gpt4 book ai didi

perl - 两次评估只读变量时的不同结果

转载 作者:行者123 更新时间:2023-12-04 12:47:49 25 4
gpt4 key购买 nike

我注意到使用 Readonly 声明的变量模块,多次评估一个变量会产生不同的结果。

>perl -Mbigint -MReadonly -wE "Readonly my $V => 1; foreach (1..2) { say 0 + '1000000000000001' * $V };
1000000000000000
1000000000000001

这是为什么?
似乎第一次用字符串解释变量,第二次用数字上下文解释变量。我的猜测是,如果它是数字, Math::BigInteger模块将重载 '*'运算符,产生准确的结果。这是 Readonly 中的错误吗?模块,有什么办法可以避免这种情况吗?

我使用不带 Readonly::XS 的 perl 5.10 和 Readonly 1.03 .

我可以用
  • v5.10.0MSWin32-x86-multi-thread (ActivePerl)
  • v5.10.0在 Linux 上 x86_64-linux-thread-multi .
  • v5.12.0在 Windows 上 (ActivePerl)

  • 我不会发生 v5.14.2 (ActivePerl),但是。

    我还用 Readonly 1.04 复制了它。我不太确定这是否相关,但 Scalar::Util::looks_like_number行为类似:
    >perl -MReadonly -MScalar::Util -Mbigint -wE "say $Readonly::VERSION; Readonly my $V => 1; foreach (1..2) { say Scalar::Util::looks_like_number $V; }"
    1.04
    0
    1

    最佳答案

    使用 tie 时似乎是一个过载错误d 在更新的 perl 版本中修复的变量。
    以下示例程序显示了差异:

    use strict;
    use warnings;
    use 5.010;

    sub TIESCALAR {
    bless {}, 'main';
    }

    sub FETCH {
    say 'FETCH';
    shift;
    }

    use overload
    '+' => sub { say 'add called'; },
    '0+' => sub { say 'tonum called'; };

    tie my $a, 'main';
    my $b = bless {}, 'main';

    say "adding non-tied (call $_): ", $b+1 for (1..2);
    say "adding tied (call $_): ", $a+1 for (1..2);

    使用 Perl 输出 v5.10.0 :
    add called
    adding non-tied (call 1): 1
    add called
    adding non-tied (call 2): 1
    FETCH
    tonum called
    adding tied (call 1): 2
    add called
    adding tied (call 2): 1

    Perl 尝试数字转换 0+重载前 +运算符在第一次评估绑定(bind)变量时,导致标准 perl 算术。在 perl 版本 >= 5.14 中,输出如预期:
    add called
    adding non-tied (call 1): 1
    add called
    adding non-tied (call 2): 1
    FETCH
    add called
    adding tied (call 1): 1
    FETCH
    add called
    adding tied (call 2): 1

    来自 perldoc overload :
    BUGS
    ....
    Before Perl 5.14, the relation between overloading and tie()ing was
    broken. Overloading was triggered or not based on the previous
    class of the tie()d variable.

    This happened because the presence of overloading was checked too
    early, before any tie()d access was attempted. If the class of the
    value FETCH()ed from the tied variable does not change, a simple
    workaround for code that is to run on older Perl versions is to
    access the value (via "() = $foo" or some such) immediately after
    tie()ing, so that after this call the previous class coincides with
    the current one.

    关于perl - 两次评估只读变量时的不同结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21185590/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com