我正在编写一些代码,其中我使用子例程作为左值和右值来读取和写入数据库值.问题是,我希望它根据它是用作左值还是右值来做出不同的反应.
我希望子程序在用作左值时写入数据库,并在数据库用作右值时从数据库中读取.
例:
# Write some data $database->record_name($subscript) = $value; # Read some data my $value = $database->record_name($subscript);
我能想到的唯一方法就是找到一种方法让子程序识别它是用作左值还是右值,并对每种情况做出不同的反应.
有没有办法做到这一点?
解决方法
决定如何调用它是否被称为左值是一个坏主意,因为foo(record_name(…))会将其称为左值.
相反,您应该决定如何将其用作左值.
你可以通过返回magical value来做到这一点.
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; }
一点测试:
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.
输出:
get: abc def set: abc def xyz get: abc def set: abc def xyz
看到这个之后,你肯定知道你应该放弃使用左值子的想法.可以隐藏所有这些复杂性(例如使用sentinel
),但复杂性仍然存在.这种复杂性并不值得.使用单独的setter和getter或使用一个访问器,其角色基于传递给它的参数数量($s = acc(); vs acc($s)).