Perl 重载 @{} 以便您可以为 foreach() 提供一个对象

标签 perl operator-overloading

有没有办法让一个类重载数组解引用器,这样我就可以将该类的一个实例提供给 foreach 并在每次迭代时运行一个自定义函数?

我试过:

  • 重载 @{} 并将其分配给子。但是,在这种情况下, sub 只执行一次,并且应该返回对要迭代的数组的引用。几乎但不完全是我想要的。
  • 重载 <> 。这将在每次读取尝试时执行分配的功能。正是我想要的,但是它适用于 while 循环,而不适用于 foreach

  • 重载.pl
    use overloaded;
    
    $class = overloaded->new();
    
    $class->add("Hi");
    $class->add("Hello");
    $class->add("Yeet");
    
    foreach $string (@$class) {
        print("NEXT ITEM: ".$string."\n");
    }
    
    while ($item = <$class>) {
        print("NEXT ITEM: ".$item."\n");
    }
    

    重载.pm
    package overloaded;
    
    use strict;
    use warnings;
    use Data::Dumper;
    use overload '@{}' => \&next, '<>' => \&fetchNext;
    
    sub new {
        my ($class, %args) = @_;
        $args{fields} = ();
        $args{pos} = 0;
        return bless { %args }, $class;
    }
    
    sub add {
        my ($self, $elem) = @_;
        push(@{$self->{fields}}, $elem);
    }
    
    sub fetchNext {
        my ($self) = @_;
        print("reading next line...\n");
        return $self->{fields}->[$self->{pos}++];
    }
    
    sub next {
        my ($self) = @_;
        print ("getting next array item\n");
        return \@{$self->{fields}};
    }
    
    1;
    

    输出:
    $ perl overloading.pl
    getting next array item
    NEXT ITEM: Hi
    NEXT ITEM: Hello
    NEXT ITEM: Yeet
    
    
    reading next line...
    NEXT ITEM: Hi
    reading next line...
    NEXT ITEM: Hello
    reading next line...
    NEXT ITEM: Yeet
    reading next line...
    

    最佳答案

    您在这里遇到的问题不是 @{...} 之间的区别和 <...>foreach之间的区别和 while .

    一个 while循环的行为有点像迭代器,因为它的执行看起来像这样:

    while (you can run a piece of code and get back a value) {
      do something
    }
    

    所以每次循环时,它都会执行 while 中的一段代码。条件并期望获得单个值。 while中的代码条件在标量上下文中运行。

    一个 foreach另一方面,循环只执行一次它的代码并期望得到一个值列表。循环开始处括号之间的代码在列表上下文中执行。

    这就是为什么您使用以下命令一次一行读取一个大文件的原因:
    while (<$file_handle>) {
      ...
    }
    

    这一次只能从文件中读取一条记录。如果您使用的是 foreach像这样循环:
    foreach (<$file_handle>) {
      ...
    }
    

    那么您将立即从文件句柄中取回所有记录 - 显然,这需要更多的内存。

    取消引用数组引用也是如此。您可以同时获取所有值。被覆盖的方法 ( next() ) 只会被调用一次,并且预计会返回一个值列表。

    关于Perl 重载 @{} 以便您可以为 foreach() 提供一个对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55903248/

    相关文章:

    perl - 如何从 Perl 使用 Active Directory?

    regex - 如何在 Perl 中访问匹配序列?

    C++:强制编译器使用两个竞争运算符之一

    c++ - C++ 运算符重载返回中的常量正确性

    c++ - 需要帮助运算符重载以便我可以显示函数

    perl - LWP 无法在 CGI 脚本中运行

    perl - 当键是动态的时在Perl中对哈希排序

    c++ - 如何用移动语义重载一元算术

    perl - 如何在perl中创建多个对象并访问相同的方法?

    c++ - 重载流插入运算符?