tlm has asked for the wisdom of the Perl Monks concerning the following question:

Update: Problem solved. Thanks, BrowserUk.


Fellow monks,

Below is code for automatically generating accessor methods with an lvalue attribute.

According to the docs, attributes in general are not available for anonymous subs, which means that the common approach of generating methods by dynamically aliasing closures can't be used if one wants these methods to have an lvalue attribute.

The only alternative I can think of is eval'ing dynamically generated strings. I'm not crazy about this, but a prototype I threw together works well enough, so I thought I'd run it by you folks, in case there are pitfalls I have overlooked. Below is the code along with a brief demo. Your comments would be much appreciated.


# Accessor_Factory.pm use strict; use warnings; package Accessor_Factory; 1; # appease the wrath of require sub make_getsets { my @fields = @_; my $class = caller; for my $field ( @fields ) { my $code = <<EOCODE; { package $class; use Carp 'carp'; sub $field : lvalue { my \$self = shift; carp "Only first argument to method $field of class $class is +used" if \@_ > 1; \$self->{ $field } = shift if \@_; \$self->{ $field }; } } 1; EOCODE eval $code or die $@; } return; } __END__

# Foo.pm use strict; use warnings; package Foo; 1; BEGIN { use Accessor_Factory; Accessor_Factory::make_getsets( qw( bar baz ) ); } sub new { return bless +{}, shift; } __END__

# demo.pl use strict; use warnings; use Foo; my $foo = Foo->new(); $foo->bar = 1; print $foo->bar, "\n"; $foo->bar += 2; print $foo->bar, "\n"; $foo->bar( 5 ); print $foo->bar, "\n"; print $foo->baz = 8, "\n"; print $foo->baz *= 11, "\n"; print $foo->baz( 100 ), "\n"; __END__

1 3 5 8 88 100

Update: Added a few more cases to the demo.

the lowliest monk

Replies are listed 'Best First'.
Re: RFC: Autogenerating lvalue methods
by BrowserUk (Patriarch) on Jul 01, 2005 at 19:39 UTC

    Maybe I am missing something?

    $x = sub:lvalue { $y };; $x->() = 3;; print $y;; 3

    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    Lingua non convalesco, consenesco et abolesco. -- Rule 1 has a caveat! -- Who broke the cabal?
    "Science is about questioning the status quo. Questioning authority".
    The "good enough" maybe good enough for the now, and perfection maybe unobtainable, but that should not preclude us from striving for perfection, when time, circumstance or desire allow.

      Thanks, that's good to know. On closer reading I realize I misinterpreted the following passage in the docs:

      ...there is no provision for applying package attributes to 'cloned' copies of subroutines used as closures.
      I misinterpreted this as referring to all closures.

      the lowliest monk

Re: RFC: Autogenerating lvalue methods
by dragonchild (Archbishop) on Jul 01, 2005 at 18:47 UTC
    Don't pooh-pooh eval so quickly. Class::MakeMethods and Class::MethodMaker both use it to generate accessors. In the right situation, it's an essential tool.

    My criteria for good software:
    1. Does it work?
    2. Can someone else come in, make a change, and be reasonably certain no bugs were introduced?