检查子例程是否在Perl中用作左值或右值

tjw*_*992 8 perl rvalue subroutine lvalue

我正在编写一些代码,其中我使用子例程作为左值和右值来读取和写入数据库值.问题是,我希望它根据它是用作左值还是右值来做出不同的反应.

我希望子程序在用作左值时写入数据库,并在数据库用作右值时从数据库中读取.

例:

# Write some data
$database->record_name($subscript) = $value;

# Read some data
my $value = $database->record_name($subscript);
Run Code Online (Sandbox Code Playgroud)

我能想到的唯一方法就是找到一种方法让子程序识别它是用作左值还是左值,并对每种情况做出不同的反应.

有没有办法做到这一点?

ike*_*ami 5

决定如何调用它是否被称为左值是一个坏主意,因为foo(record_name(...))它将它称为左值.

相反,您应该决定如何将其用作左值.

你可以通过返回一个神奇的值来做到这一点.

use Variable::Magic qw( cast wizard );

my $wiz = wizard(
   data => sub { shift; \@_ },
   get => sub { my ($ref, $args) = @_; $$ref = get_record_name(@$args); },
   set => sub { my ($ref, $args) = @_; set_record_name(@$args, $$ref); },
);

sub record_name :lvalue {
   cast(my $rv, $wiz, @_);
   return $rv;
}
Run Code Online (Sandbox Code Playgroud)

一点测试:

use Data::Dumper;

sub get_record_name { print("get: @_\n"); return "val"; }
sub set_record_name { print("set: @_\n"); }

my $x = record_name("abc", "def");        # Called as rvalue

record_name("abc", "def") = "xyz";        # Called as lvalue. Used as lvalue.

my $y_ref = \record_name("abc", "def");   # Called as lvalue.
my $y = $$y_ref;                          #   Used as rvalue.
$$y_ref = "xyz";                          #   Used as lvalue.
Run Code Online (Sandbox Code Playgroud)

输出:

get: abc def
set: abc def xyz
get: abc def
set: abc def xyz
Run Code Online (Sandbox Code Playgroud)

看到这个之后,你肯定知道你应该放弃使用左值子的想法.隐藏所有复杂性(例如通过使用sentinel)是可能的,但复杂性仍然存在.这种复杂性并不值得.使用单独的setter和getter或使用一个访问者,其角色基于传递给它的参数数量($s=acc();vs acc($s)).

  • 哈哈,这个答案令人难以置信.最后我决定完全避免使用左值子程序,但我真的很感兴趣的是返回神奇的价值观! (3认同)