【问题标题】:What are the uses of lvalue subroutines in Perl?Perl 中左值子例程的用途是什么?
【发布时间】:2009-02-02 20:56:32
【问题描述】:

我不明白左值子例程的用途是什么?什么是我用普通子程序无法完成的?可以发一些例子吗?

谢谢

【问题讨论】:

    标签: perl subroutine lvalue


    【解决方案1】:

    您可以使用左值子作为对象成员的设置器:

    sub x : lvalue {
        my $self = shift;
        $self->{x};
    }
    

    然后:

    $foo->x = 5;
    

    这结合了直接设置成员的直观性和封装 setter 的灵活性,以防您以后想要更改对象的实现方式。与以下在 Perl 中设置成员的更传统方法相比:

    直观但脆弱;如果你改变 $foo 的实现方式会怎样?

    $foo->{x} = 5;
    

    传统的setter方法;不使用赋值语法来表示赋值:

    $foo->set_x(5);
    

    当然,Perl 社区从未真正接受过左值方法,并且使用左值 subs 是“奇怪的”,任何为了直观而获得的东西都会因为这一切的陌生而丢失。

    【讨论】:

    • 请注意,就像manual 状态一样,对这样的设置器使用左值 subs 排除了验证输入的可能性。换句话说,使用左值 subs 作为访问器严格来说不如普通方法强大。
    • 是的,就像 'C' 或 C++ 中的 'struct' 成员一样——没有任何东西可以验证对 struct 成员的分配。然而,没有人认为这是 'struct's 的问题。
    【解决方案2】:

    建议避免使用 LValue。它们很有趣,但它们会让新用户感到困惑,因为他们会假设所有子程序是如何工作的,因此当有更好的方法可用时,应该在代码中避免它。

    有时使用 LValue 结果来做脏活是非常实用的。

    substr( $string, $start, $stop ) = 'somevalue' # replaces the specified part of the substring. 
    

    但是,这也做同样的事情:

    substr( $string, $start, $stop , 'somevalue' ); 
    

    这里的区别主要是前者具有更强的表达能力,因为它将行为委托给使用它的代码而不是函数本身。

    例如:

    substr( $string, $start, $stop ) =~ s/a/b/g 
    

    需要你做

    my $x = substr( $string, $start, $stop ); 
    $x =~ s/a/b/g/; 
    substr( $string, $start, $stop, $x );
    

    这有点讨厌。

    虽然,这里还有一个令人讨厌的地方,因为您必须考虑是否使用 $x 进行替换是否可以追溯修改字符串(因为 substr 是 LValue 子)。我不认为它有,但它的模棱两可,我必须检查手册才能记住它是否有,这很糟糕。

    【讨论】:

    • $x 包含一个副本,而不是左值。但是,如果您为左值 substr ala for (substr(...)) {foo(substr(...)) 取别名,您可以用左值做不止一件事。
    • 我无法理解您的一些短语:A) “使用 LValue 结果来做脏活。”但是我在示例中看不到这一点-或者我不明白您所说的“LValue 结果”B)是什么意思,因为它将行为委托给使用它的代码而不是函数本身。也许这是关于非母语英语,但我对这里的代词含义感到困惑
    • 和 C) “因为您必须考虑是否使用 $x 进行替换是否可以追溯修改字符串”——我太不清楚了,甚至无法指出如何正是……
    【解决方案3】:

    它们提供了不同的界面,在某些情况下可以更直观。与传统的 setter 不同,您实际上可以直接更改值。例如

    lvalue_sub($foo) =~ s/foo/bar/;
    

    可以比

    更干净
    my $tmp = some_sub($foo);
    $tmp =~ s/foo/bar/;
    some_sub($foo, $tmp);
    

    【讨论】:

      【解决方案4】:

      我不能说在我的普通 Perl 东西中使用它们太多,但是在获取切片或 piddle 的其他小节时,它们在 Perl 数据语言中被广泛使用。例如:

      my $a = sequence(100);
      # use lvalue in this increment:
      $a->where($a < 10)++;
      
      # Zero-out the last four elements
      # notice the use of the overloaded .= operator:
      $a->slice("-10:") .= 0;
      

      与 Perl 中的许多东西一样,此功能在整个生态系统中的使用并不多,但它至少在这个利基市场中的使用使 PDL 用户的生活更加更轻松。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2023-04-07
        • 2020-01-21
        • 2013-12-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-09-06
        • 2011-02-09
        相关资源
        最近更新 更多