【问题标题】:Why doesn't "use overload" work with "use namespace:autoclean"?为什么“使用重载”不能与“使用命名空间:自动清洁”一起使用?
【发布时间】:2012-04-20 18:03:43
【问题描述】:

好吧,只是为了理智检查过载似乎对我不起作用。我不知道是我的perl版本,还是overload.pm的版本,还是我实现它的方式有问题,但是这段代码对我不起作用。

perl 版本

This is perl, v5.10.1 (*) built for x86_64-linux-gnu-thread-multi

重载版本

perl -Moverload -e 'print "$overload::VERSION\n";'
1.07

令牌.pm

package Token;
use namespace::autoclean;
use Data::Dumper;


use Moose;
use Moose::Util::TypeConstraints; 

use overload '+' => \&_overload_add, fallback => 1;

  has 'secretvalue' => ( is => 'rw', isa => 'Int');  

  sub _overload_add{
    my ( $one, $two ) = @_;   
    my $value = $one->secretvalue() + $two->secretvalue();
    return ($value);
  }

主要

use strict;
use warnings;
use Token;
my $t = Token->new( secretvalue => 17, key => 'x' );
my $t2 = Token->new( secretvalue => 12, key => 'y' );

my $x = $t + $t2;

print $x;

打印

 $VAR1 = 12900840;

最糟糕的是,我在日志中没有收到任何警告或错误。

更新

感谢 Freido 发现问题。我已经更新了这个问题,以防其他人偶然发现这个问题。

Perl/Moose 社区一般不使用重载吗?

【问题讨论】:

    标签: perl namespaces overloading moose


    【解决方案1】:

    namespace::autoclean 正在使用overload 添加的用于处理您的操作员的魔法。以下工作如您所料:

    package Token;
    
    use Moose;
    use Moose::Util::TypeConstraints;
    
    use overload '+' => '_overload_add';
    
    has 'secretvalue' => ( is => 'rw', isa => 'Int');
    
    sub _overload_add{
        my ( $one, $two ) = @_;
        my $value = $one->secretvalue() + $two->secretvalue();
        return ($value);
    }
    
    1;
    

    随便一瞥并没有发现namespace::autoclean 文档中解决这个问题的任何内容,所以我猜这是一个意料之外的功能。一些搜索显示,bug 已被举报。

    我猜它归结为 overload 添加到您的包中的特殊符号。重载+ 会添加符号表条目()(+OVERLOAD。我猜这些部分或全部都被namespace::autoclean 吸走了,从而消除了你的超载。

    如果您喜欢冒险,here's a patch for namespace::autoclean 会过滤掉过载符号。

    【讨论】:

    • +1 用于在我用头敲桌子一两个小时试图找到我的代码问题后找到解决方案。愚蠢的图书馆错误!
    • 去过那里,做到了。 :) 我也对你的问题感到困惑,直到我想起 overload 通过插入魔术符号来工作,我想知道 autoclean 是否在搞乱它们。
    • @nodebunny,既然可以自己写代码,为什么还要抱怨别人的代码呢? :) 这个问题启发了我写namespace::sweep 这不会践踏你的超载。更多信息here.
    【解决方案2】:

    所以friedo 是绝对正确的;问题在于启发式 Class::MOP 用于确定什么是“方法”,什么不是“方法”。通常,从另一个包导入的任何东西都不是方法,从技术上讲,重载就是这样。由于 namespace::autoclean 询问 Class::MOP 包存在哪些方法并删除其余方法,因此 autoclean 会盲目清除重载以及其他所有方法。

    我认为这非常令人惊讶。

    MooseX::MarkAsMethods 将为 Moose 课程提供帮助;它在 autoclean 之前运行,并告诉 Moose 将该包的任何重载代码符号识别为方法。这使他们免于使用自动清理的斧头,并具有额外的优势,现在您可以在角色中使用重载,使用它们,并让它们“正常工作”。 (完全披露:我在 2 年前我的自动清理修复被拒绝后写了 MX::MarkAsMethods。)

    但是,这对您可能希望使用 autoclean 的非 Moose 类没有帮助... autoclean 删除重载充其量是 autoclean 中的一个缺陷。

    【讨论】:

    • flaw 太客气了,namespace::autoclean 也因此而彻底崩溃。顺便说一句,您的修复是完美的,维护者对此很固执,这是一种耻辱。
    【解决方案3】:

    我也遇到过同样的问题(在我的情况下尝试重载 ""),但还没有让 MooseX::MarkAsMethods 工作。还没有研究为什么正确,但是确实工作的替代修复是使用MooseX::Role::WithOverloading(因为我已经使用了各种角色,它很容易适应)。

    package MyClass;
    use Moose;
    use namespace::autoclean;
    with 'MyRole';
    
    package MyRole;
    use MooseX::Role::WithOverloading;
    
    use overload '""' => sub { ... };
    

    【讨论】:

      猜你喜欢
      • 2020-09-13
      • 1970-01-01
      • 2010-12-22
      • 1970-01-01
      • 2023-04-04
      • 1970-01-01
      • 2014-04-13
      • 2013-06-23
      • 2015-02-24
      相关资源
      最近更新 更多