Why is initializer going away?

2010-10-25 Thread Evan Carroll
I personally use initializer a lot in my Moose code, yet I hear a lot
of people saying negative things about it? What's wrong initializer
and is it going away? I often find its hook-choice more useful than
trigger.

-- 
Evan Carroll - m...@evancarroll.com
System Lord of the Internets
web: http://www.evancarroll.com
ph: 281.901.0011


Re: Why is initializer going away?

2010-10-25 Thread Dave Rolsky

On Mon, 25 Oct 2010, Evan Carroll wrote:


I personally use initializer a lot in my Moose code, yet I hear a lot
of people saying negative things about it? What's wrong initializer
and is it going away? I often find its hook-choice more useful than
trigger.


It's not going away, to the best of my knowledge. I've de-emphasized it in 
the docs, simply because it seems like a niche feature, and I've tried to 
make the Manual focus on features most people are likely to use early on 
in the Moose-life.



-dave

/*
http://VegGuide.org   http://blog.urth.org
Your guide to all that's veg  House Absolute(ly Pointless)
*/


Re: [TEST CASE] Constructor provided arguments and strict-default fire ordering is confusing or buggy.

2010-10-25 Thread Jesse Luehrs
On Mon, Oct 25, 2010 at 03:28:26PM -0500, Evan Carroll wrote:
 I've recently discovered that rather against my own intuition Moose
 does not set constructor provided arguments first. I've always thought
 that Moose did the logical thing here.. If I was to read the code
 here:
 
 Class-new({ foo = bar })-baz;
 
 I'd have assumed that the process went like this:
 * BUILDARGS if any
 * Moose provided-new which sets the attributes to the values in the hashref
 * The default/initializer stage (undefined for the class, defined for
 the attribute)
 * BUILD which gets the complete object
 
 However, I'm now seeing this. The non-lazy defaults fire before `foo`
 get's set even though foo is explicitly provided. This seems awkward
 and counter-intuitive. You can find a test case here
 http://gist.github.com/645659 . Could anyone provide commentary on
 this behavior? Is this a bug in Moose. I'm on latest stable: 1.17.

This is not a bug. Attribute initialization order is explicitly
undefined (the documentation mentions this in several places). If you
need a defined initialization order, you should make the appropriate
attributes lazy.

-doy


Re: [TEST CASE] Constructor provided arguments and strict-default fire ordering is confusing or buggy.

2010-10-25 Thread Evan Carroll
 This is not a bug. Attribute initialization order is explicitly
 undefined (the documentation mentions this in several places). If you
 need a defined initialization order, you should make the appropriate
 attributes lazy.

That's not how I read that statement. When you say attribute
initialization order is undefined I read that literally. Example,

has foo = ( isa = Int, is = ro, default = 1 );
has bar = ( isa = Int, is = ro, default = 2 );

Is undefined such that foo, and bar will be set in an undefined
order. Not, that the constructor provided arguments and
strict-defaults are undefined. I don't even read initialization as
being an apt choice of words for setting foo, via

Class-new({ foo = bar })

I'm not sure if this misunderstanding is unique to myself or not, but
I didn't take your statement (or the docs) to be at odds with my own
mental model of Moose behavior.

-- 
Evan Carroll - m...@evancarroll.com
System Lord of the Internets
web: http://www.evancarroll.com
ph: 281.901.0011


Re: [TEST CASE] Constructor provided arguments and strict-default fire ordering is confusing or buggy.

2010-10-25 Thread Hans Dieter Pearcey
On Mon, 25 Oct 2010 15:28:26 -0500, Evan Carroll m...@evancarroll.com wrote:
 I'd have assumed that the process went like this:
 * BUILDARGS if any

yes

 * Moose provided-new which sets the attributes to the values in the hashref
 * The default/initializer stage (undefined for the class, defined for
 the attribute)

* Initialize each attribute in turn, from constructor argument or
  default/builder

Also, I have no idea what your parenthetical means.

 * BUILD which gets the complete object

yes

 However, I'm now seeing this. The non-lazy defaults fire before `foo`
 get's set even though foo is explicitly provided. This seems awkward
 and counter-intuitive. You can find a test case here
 http://gist.github.com/645659 . Could anyone provide commentary on
 this behavior? Is this a bug in Moose. I'm on latest stable: 1.17.

Awkward and counter-intuitive is very subjective and therefore not a
compelling reason to change things; for example, people regularly seem to think
that it is awkward and counter-intuitive not to override new() when coming from
vanilla Perl 5 OO.

In this particular case, the way Moose does things means that code related to a
given attribute (default, etc.) only sees that particular attribute in a
half-built state -- that is, each other attribute is either completely
initialized or not at all.  This means there's much less opportunity for your
object to be exposed in an inconsistent state.

hdp.


Re: [TEST CASE] Constructor provided arguments and strict-default fire ordering is confusing or buggy.

2010-10-25 Thread Evan Carroll
 Also, I have no idea what your parenthetical means.

Parenthetical indicate that I know default fires before the
initializer for the attribute, but that not all defaults for all
attributes will fire before any of the initializers. Currently, an
Attribute process not a class process.

 Awkward and counter-intuitive is very subjective and therefore not a
 compelling reason to change things; for example, people regularly seem to 
 think
 that it is awkward and counter-intuitive not to override new() when coming 
 from
 vanilla Perl 5 OO.

 In this particular case, the way Moose does things means that code related to 
 a
 given attribute (default, etc.) only sees that particular attribute in a
 half-built state -- that is, each other attribute is either completely
 initialized or not at all.  This means there's much less opportunity for your
 object to be exposed in an inconsistent state.

I don't see the logic in the term inconsistent. I've showed the flow
defined in a sequential list in my original post, maybe you can
clarify why you feel such a flow is inconsistent. I'll go ahead and
show you what I wanted to do with this. I have a Class, it should
accept either a company_id, or a hash of attributes if you provide
a company_id the attribute hash is lazy when it is needed. If you
provide a hash of company attributes, then the value is immediately
entered into the DB, and the company_id gets set appropriately:

has 'attr' = (
  isa   = 'HashRef'
  , is  = 'ro'
  , lazy= 1
  , predicate = '_has_attr'
  , default = sub {
my $self = shift;
die No company id unless $self-_has_company;
# Get from db.
  }
);

has 'company' = (
  isa  = 'Int'
  , is = 'ro'
  , predicate = '_has_company'
  , default = sub {
my $self = shift;
die 'No attributes or company id' unless $self-_has_attr;
# Insert into DB
  }
)

Anyway, it just seems very naturally that this should work. You're
explicitly providing non-defaults for some attributes, but they're
order is undefined until other attribute's get their defaults -- it
seems like the current method provides no gain whatsoever.

-- 
Evan Carroll - m...@evancarroll.com
System Lord of the Internets
web: http://www.evancarroll.com
ph: 281.901.0011


Re: [TEST CASE] Constructor provided arguments and strict-default fire ordering is confusing or buggy.

2010-10-25 Thread Hans Dieter Pearcey
On Mon, 25 Oct 2010 16:23:45 -0500, Evan Carroll m...@evancarroll.com wrote:
 I'll go ahead and
 show you what I wanted to do with this. I have a Class, it should
 accept either a company_id, or a hash of attributes if you provide
 a company_id the attribute hash is lazy when it is needed. If you
 provide a hash of company attributes, then the value is immediately
 entered into the DB, and the company_id gets set appropriately:

Using new() for this seems wrong to me.  Your object constructor should
construct objects, not construct objects and sometimes insert data but other
times retrieve it.  For example, in DBIC this is find_or_create, which is
itself built on top of other predicates that are built on top of object
construction; it's a complex operation, and trying to make it all an
inextricable part of calling new is a code smell.

If you insist on doing it anyway, I don't think you'll find any support for the
approach you've chosen, because we've repeatedly said that using 'lazy' on
everything is the right way to deal with this kind of attribute
interdependency.  Using lazy already gives you the initialization order that
you want.

In this particular case, you could mark everything as lazy and resolve it in
BUILD.  If you find that unappealing, this would also be a good use of the
hypothetical lazy default/builder, but call it automatically after
initialization attribute trait/option that's come up with some frequency in
the past, if you felt like writing that.

hdp.