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

I'm experimenting with Object::Tiny which seems useful and is lightweight for very simple objects. I'd like to make it a little more useful by being able to set properties:

$file->headers(\@headers);

This doesn't work. So I'm thinking of writing a set method:

sub set { my $s = shift; my $attribute = shift; my $value = shift; $s->{$attribute} = $value; }

But maybe this is horrible in a number of ways and I should use a slightly heavier module for creating objects?

Replies are listed 'Best First'.
Re: Setting accessor with Object::Tiny
by haukex (Archbishop) on Aug 11, 2019 at 20:21 UTC
    I should use a slightly heavier module for creating objects?

    IMO: Yes. :-) I usually use Moo. Of course it's also possible to auto-generate the acessor methods yourself, but that starts being too much reinvention of the wheel. Or maybe consider Mo...

    Update: Added a missing word.

Re: Setting accessor with Object::Tiny
by NetWallah (Canon) on Aug 11, 2019 at 21:26 UTC
    Here is my suggestion to improve Object::Tiny to allow for these features:

    UPDATE: Added "Extra parameters" feature to callbacks; improved example.

    use strict; use warnings; {package Object::Tiny;} {package Foo; use parent -norequire ,"Object::Tiny"; Object::Tiny::->import( qw|bar baz headers myhash|); } my $f = Foo::->new(bar=>44, baz=>"Value of baz"); $f->headers_set(["This is H-1","This is H-2"]); # SETTER - sets arrayr +ef print "Object f Scalar: $_=> ",$f->$_,";\n" for qw |baz bar |; # Get a callback for each member of array ref: $f->headers_forEach(sub{print "Object f :(Array component) header=$_[0 +];\n"}); $f->baz_forEach(sub{print "Object f : (Scalar accessed as array) baz v +alue=$_[0];\n"}); $f->myhash_set({Uno=>"One", Dos=>"Two", Tres=>"Three"}); # Setter - se +ts hashref # Get a callback for each KEY. # Extra parameters (R/W) returned are the extra param passed to forEac +h() $f->myhash_forEach(sub{print "Object f (HashRef): myhash KEY:$_[0]; VA +LUE:$_[1]; Extra args($_[2],", ++$_[3],")\n"}, "Extra-arg1", 25);
    (You can append THIS version of the module directly to the code above, to make it work) OUTPUT:
    $ perl test-obj-tiny.pl Object f Scalar: baz=> Value of baz; Object f Scalar: bar=> 44; Object f :(Array component) header=This is H-1; Object f :(Array component) header=This is H-2; Object f : (Scalar accessed as array) baz value=Value of baz; Object f (HashRef): myhash KEY:Dos; VALUE:Two; Extra args(Extra-arg1,2 +6) Object f (HashRef): myhash KEY:Tres; VALUE:Three; Extra args(Extra-arg +1,27) Object f (HashRef): myhash KEY:Uno; VALUE:One; Extra args(Extra-arg1,2 +8)
    I'm too lazy to document this, and propose the update to the module author (Never contributed to CPAN). Please feel free to do this on my behalf.

                    "From there to here, from here to there, funny things are everywhere." -- Dr. Seuss

Re: Setting accessor with Object::Tiny
by karlgoethebier (Abbot) on Aug 12, 2019 at 09:21 UTC
    "...by being able to set properties...a slightly heavier module for creating objects?"

    You want them on-the-fly? See also Class::Tiny. Regards, Karl

    «The Crux of the Biscuit is the Apostrophe»

    perl -MCrypt::CBC -E 'say Crypt::CBC->new(-key=>'kgb',-cipher=>"Blowfish")->decrypt_hex($ENV{KARL});'Help

Re: Setting accessor with Object::Tiny
by jcb (Parson) on Aug 12, 2019 at 03:03 UTC

    I generally just use the Perl core object system rather than pulling in other packages. For what Object::Tiny gives you, have you considered using the core fields pragma instead?

    I have often used an internal _set method like: (disclaimer: this exact code not tested)

    sub _set { my $self = shift; my ($key, $value); while (($key, $value) = splice @_, 0, 2) { $self->{$key} = $value +} }
      sub _set { my $self = shift; my ($key, $value); while (($key, $value) = splice @_, 0, 2) { $self->{$key} = $value +} }

      For this, why not just:

      c:\@Work\Perl\monks>perl -wMstrict -MData::Dump -le "sub _set { my $self = shift; %$self = (%$self, @_); } ;; my $hr = bless { qw(y 25 z 26) }; ;; $hr->_set(qw(a 1 b 2 c 3)); dd $hr; " bless({ a => 1, b => 2, c => 3, "y" => 25, z => 26 }, "main")


      Give a man a fish:  <%-{-{-{-<

        Because I had not thought of that? :-) It figures that there would be a more compact way to do that.

        Although if I had objects being mutated in an inner loop, I would want to compare both ways, in case changing a few keys is faster than setting the whole hash.

Re: Setting accessor with Object::Tiny
by 1nickt (Canon) on Aug 12, 2019 at 15:15 UTC

    Hi, I'd say it's too "lightweight" if you have to start hacking it :-)

    I second haukex and recommend Moo for all OOP work, even for one-liners.

    $ perl -wE 'package Foo { use Moo; has bar => (is => "rw", isa => sub +{ die "invalid" unless shift =~ /^[a-z]+$/ }) }; my $o = Foo->new(bar + => "baz"); $o->bar("qux"); say $o->bar; $o->bar(42)' qux isa check for "bar" failed: invalid at -e line 1.

    Hope this helps!


    The way forward always starts with a minimal test.