http://www.perlmonks.org?node_id=1012900


in reply to Re: Possible issue with Moose ScalarRef
in thread Possible issue with Moose ScalarRef

Thanks for all your tests! It means I'm not crazy! But that is a very strange behavior!

You mentioned "changing data via the reference", I want to do the opposite in fact, changing the data in the original variable so I can reference to it from another object. I guess the result is the same.

Anyway, I found a workaround, and it seems to do what I want, but I still have a different SCALAR address for the original and the reference. I now do this:

my $obj = Something->new( { # Before: #'debug_level' => \$self->debug_level, # Now: 'debug_level' => \$self->{'debug_level'}, } );

Do you think it would always work, or is it "random" like the previous way?

Testing never proves the absence of faults, it only shows their presence.

Replies are listed 'Best First'.
Re^3: Possible issue with Moose ScalarRef
by tobyink (Canon) on Jan 11, 2013 at 15:44 UTC

    It will work for objects which are internally implemented as hashrefs. Moose does this by default, and it's quite a bit of work to persuade it to implement objects any other way.

    (There are various MooseX modules on CPAN that can do that work for you, including MooseX::InsideOut and my own MooseX::ArrayRef which allows you to create Moose classes based on arrayrefs.)

    It is generally considered poor style to peek at the hashref internals of Moose objects (indeed, blessed objects in general). One good reason is that if you're relying on a module's internals, it gives the module's author less freedom to refactor those internals.

    In this case, when you appear to be the author of both modules, so the above might not be a concern, the strong argument against poking the hashref is that it bypasses type constraint checks.

    One alternative solution might be to pass a closure from your first class to your second class...

    use strict; use warnings; use Test::More; { package Thing; use Moose; has attr => (is => 'rw'); sub get_closure { my $self = shift; return sub { $self->attr(@_) }; } } { package ThingWithRef; use Moose; has closure => (is => 'ro'); sub translate_to_dutch { my $self = shift; my $str = $self->closure->(); $str =~ s/e/a/; $self->closure->($str); } } my $obj1 = Thing->new(attr => 'Hello'); my $obj2 = ThingWithRef->new(closure => $obj1->get_closure); $obj2->translate_to_dutch; is($obj1->attr, 'Hallo'); done_testing;
    perl -E'sub Monkey::do{say$_,for@_,do{($monkey=[caller(0)]->[3])=~s{::}{ }and$monkey}}"Monkey say"->Monkey::do'

      Thanks again! I will think about it and find the best, long-term solution.

      Testing never proves the absence of faults, it only shows their presence.