Skip Menu |

This queue is for tickets about the Moo CPAN distribution.

Report information
The Basics
Id: 127000
Status: open
Priority: 0/
Queue: Moo

People
Owner: Nobody in particular
Requestors: valderrama [...] strato.de
Cc:
AdminCc:

Bug Information
Severity: (no value)
Broken in: (no value)
Fixed in: (no value)



Subject: Attribute initialization vs Module loading
Date: Thu, 30 Aug 2018 15:12:53 +0000
To: "bug-Moo [...] rt.cpan.org" <bug-Moo [...] rt.cpan.org>
From: "Valderrama, Mario" <valderrama [...] strato.de>
Hello, I know this is probably not the best way to do this, but creating objects of subclasses from a function in the superclass doesn't correctly initalize the attributes. Say I have 3 files: Foo.pm package Foo; use Moo; use FooBar; has foo => (is => 'ro'); sub make_foobar { FooBar->new(@_) } 1; FooBar.pm package FooBar; use Moo; extends 'Foo'; has bar => (is => 'ro'); 1; main.pl #!/usr/bin/env perl use strict; use warnings; use 5.026; use lib '.'; use Foo; my $foobar = Foo::make_foobar(foo => 'foo', bar => 'bar'); say $foobar->foo(); say $foobar->bar(); Invoking main.pl will yield the following: $ perl main.pl Use of uninitialized value in say at main.pl line 9. bar This however can be fixed by either adding a 'use FooBar;' before the 'use Foo;' in main.pl or by using Moose instead of Moo in any of the two modules. Making one of these changes will then result in: $ perl main.pl foo bar I'm using: - Perl 5.26.0 (installed with plenv) - Moo 2.003004 - Moose 2.2011 (for reference) - Fedora 28 with Kernel 4.17.18-200.x86_64

Message body is not shown because sender requested not to inline it.

Message body is not shown because sender requested not to inline it.

Message body is not shown because sender requested not to inline it.

I am running into the same issue. Attached is a sample proof.pl file. If I use Moose in place of Moo, The issue does not happen.
Subject: proof.pl
#!/opt/apps/perl/perl5240/bin/perl use Modern::Perl; { my $t=new TestThree; print $t->attr_one,"\n"; print $t->attr_two,"\n"; print $t->attr_three,"\n"; } { my $t=new TestThree(attr_one=>3,attr_two=>5,attr_three=>6); print $t->attr_one,"\n"; print $t->attr_two,"\n"; print $t->attr_three,"\n"; } BEGIN { package TestOne; use Modern::Perl; use Moo; has attr_two=>(is=>'ro',default=>2,lazy=>1); 1; package TestTwo; use Modern::Perl; use Moo; has attr_one=>(is=>'ro',default=>1,lazy=>1); 1; package TestFour; use Modern::Perl; use Moo; has attr_three=>(is=>'ro',default=>3,lazy=>1); 1; package TestThree; use Modern::Perl; use Moo; extends qw(TestOne TestTwo TestFour); 1; }
Sorry didn't mean to say fixed in. Its currently broken in version: 2.003006
On Thu Aug 30 11:19:10 2018, valderrama@strato.de wrote: Show quoted text
> Hello, > > > I know this is probably not the best way to do this, but creating > objects of subclasses from a function in the superclass > > doesn't correctly initalize the attributes. > > Say I have 3 files: > > > Foo.pm > > package Foo; > > use Moo; > > use FooBar; > > > has foo => (is => 'ro'); > > > sub make_foobar { FooBar->new(@_) } > > > 1; > > > FooBar.pm > > package FooBar; > > use Moo; > > > extends 'Foo'; > > > has bar => (is => 'ro'); > > > 1; > > > main.pl > > #!/usr/bin/env perl > > use strict; > > use warnings; > > use 5.026; > > use lib '.'; > > use Foo; > > > my $foobar = Foo::make_foobar(foo => 'foo', bar => 'bar'); > > say $foobar->foo(); > > say $foobar->bar(); > > > Invoking main.pl will yield the following: > > > $ perl main.pl > > Use of uninitialized value in say at main.pl line 9. > > > bar > > > This however can be fixed by either adding a 'use FooBar;' before the > 'use Foo;' in main.pl or by using Moose instead of Moo in any of the > two modules. > > Making one of these changes will then result in: > > > $ perl main.pl > > foo > > bar > > > I'm using: > > - Perl 5.26.0 (installed with plenv) > > - Moo 2.003004 > > - Moose 2.2011 (for reference) > > - Fedora 28 with Kernel 4.17.18-200.x86_64
This code is creating a circular dependency between Foo and FooBar. There are numerous ways this can cause problems, and this is one of them. At the time that FooBar copies the attribute information from Foo, Foo hasn't added any attributes, so FooBar doesn't know about them. It can be fixed by changing the loading order. While generally having any circular dependencies is bad, if you really need to do it, remove the 'use FooBar;' and add a line 'require FooBar;' near the end of the file.