Stevan et al., I see you have already put a considerable amount of thought into this.
- do we make the "before" trigger return a value for us to assign? - do we make the "before" trigger actually do the assignment? This is a tough one. On the one hand, having the "before" trigger return the value to be assigned seems most straight-forward. But from a usability stand point, you should want to keep the "before" and "after" triggers as similar as possible. And you don't want to restrict triggers in such a way. You want them to be able to affect other attributes has 'max' => ( ... trigger => { before => sub { $_[0]->max if $_[0]->min > $_[0]->max; } ); So yeah, I would have the "before" trigger responsible for setting the assignment. I realize this is very tricky. - what happens if an exception is thrown inside the "before", do we catch it? - how would you/should you be able to -- indicate failure or some kind in before? You would have to support some type of exception / failure handling, don't you. Perhaps this could be caught and indicated in meta and the particular exception retrievable with a sub call. Maybe you could support for a DBI-type raise error mechanism that indicates if exceptions are caught and how they are handled a la FATAL / WARN / IGNORE. In any event, I will give it some more thought. Best, Chris On Tue, Jul 15, 2008 at 5:29 PM, Stevan Little < [EMAIL PROTECTED]> wrote: > Chris, > > Yes, the key is to figure out the best place to add this feature. Trigger > fires after the assignment has been made, which in this case is too late. We > had talked about a multi-phase trigger which would allow a "before" and > "after" options, like so: > > has foo => ( > is => 'rw', > ... > trigger => { > before => sub { ... }, > after => sub { ... }, > } > ); > > this would allow the backward compat to be handled when trigger is a CODE > ref, but the new feature could be handled when it is a HASH ref. This is not > all that different then the inflate/deflate that DBIx::Class offers. > > The idea would be that the "after" would do the same as the normal trigger, > and the "before" would get the same arguments as the normal trigger except > the assignment would not have happened yet. The tricky bits are: > > - do we make the "before" trigger return a value for us to assign? > - do we make the "before" trigger actually do the assignment? > - what happens if an exception is thrown inside the "before", do we catch > it? > - how would you/should you be able to -- indicate failure or some kind in > before? > > THoughts? > > - Stevan > > > > > On Jul 15, 2008, at 4:55 PM, Christopher Brown wrote: > > Stevan, Benh, Charlie and Moose, >> >> My two cents is that ALL Moose users will eventually run into this as It >> is not too uncommon. Think of all the applications that you use where one >> of the parameters is interdependent upon another. Personally, I have used >> both triggers and BUILD, but felt that be a better way. Using BUILD seems >> like a more general solution, but BUILD separates the >> check/coercion/constraint logic from the attribute definition. IMHO, a bad >> thing. My thoughts this been that I have wanted a constraint argument to >> the 'has' function that would fire the defined subroutine just before the >> BUILD subroutine. Not sure how that would work or even if that is possible >> in the given architecture. >> >> Best, >> >> Chris >> >> >> What I have wanted is a constraint => argument to has that fires Perhaps >> there should be a constraint => argument >> >> On Tue, Jul 15, 2008 at 9:15 AM, Stevan Little < >> [EMAIL PROTECTED]> wrote: >> Well the idea of a type check/coercion that has access to $self has been >> on my mind for a while, but I have not figured out yet. Traditionally in >> most type systems, especially those which are done at compile-time, you >> don't have access to other runtime variables. There is a current research >> path on something called "Dependent Types" which brings in the notion of >> values, however this is some pretty complex stuff and some of it's >> detractors have mused that to really type a program fully you would need to >> execute it at compile-time, which means you would likely prove it can stop, >> which gets into the whole "would a language with dependent types be turing >> complete then?" question (which is also where it goes waaaaaaaay over my >> head too). >> >> That said, I think we need a better facility then triggers. >> >> My concern is that putting this into the type system makes it into "action >> at a distance" especially when it comes to coercions. It also ties a type >> specifically to a class and so removes reusability (good thing, bad thing, >> hard to say here). >> >> Anyway, it is in the back of my head, I have not forgotten about it. Part >> of me fears it will require a type system overhaul/re-write though, so it >> may not be coming soon. >> >> - Stevan >> >> >> >> >> On Jul 15, 2008, at 4:13 AM, benh wrote: >> >> It seems that at the heart of it it seems that theres a missing event >> that has access to self? My inital though was to just create a type >> that was min, but types loose there context. I've been trying to wrap >> my head around the code for this to see if there was some way to try >> and have some other specified global structure that would still be in >> scope, but I alway get lost in the passing of things when I look at >> the type code. >> >> I was able to trick things out but it requires that most of the 'built >> in' code structure gets re-done in BUILD, thus you have access to self >> and you end up forcing a system where everything passes thru a >> trigger. This allows you to check for any thing, but it does seem like >> much more of a hack then the inital example... >> >> It's a bit tedious so I posted it elsewhere: >> >> http://develonizer.com/svn/misc/min_max.pl >> >> >> >> >> >> On 7/14/08, [EMAIL PROTECTED] <[EMAIL PROTECTED]> wrote: >> How about this: >> >> has 'min' => ( >> is => 'rw', >> isa => 'Int', >> default => sub { NEGATIVE_INFINITY }, >> trigger => sub { >> my ( $self, $val ) = @_; >> carp "min is > max" unless $val <= $self->max; >> } >> ); >> >> has 'max' => ( >> is => 'rw', >> isa => 'Int', >> default => sub { POSITIVE_INFINITY }, >> trigger => sub { >> my ( $self, $val ) = @_; >> carp "max is < min" unless $val >= $self->min; >> } >> ); >> >> No BUILD needed. Consistency checked by the triggers whenever min and >> max >> are set... >> >> Besides defining negative and positive infinity, the only problem I see >> is >> if both min and max are set at the same time, as in the constructor. I >> don't know which error you'd get if the object was initialized like this: >> >> my $foo = Foo->new( >> min => 1, >> max => -1, >> ); >> >> Charles Alderman >> >> ----- Original Message ----- >> From: Guillaume Rousse <[EMAIL PROTECTED]> >> Sent: Mon, 14 Jul 2008 23:15:49 +0200 >> Re: checking consistency between attributes >> >> >> >> >> Hello list. >> >> What's the best way to check consistency between attributes values ? Is >> there anything better than a dedicated BUILD method, such as: >> >> use Moose; >> use Carp; >> >> has 'min' => (is => 'rw', isa => 'Int'); >> has 'max' => (is => 'rw', isa => 'Int'); >> >> sub BUILD { >> my ($self, $params) = @_; >> >> my ($max, $min) = ($self->max(), $self->min()); >> croak "max < min" if defined $max && defined $min && $max < $min; >> } >> -- >> Guillaume Rousse >> Moyens Informatiques - INRIA Futurs >> Tel: 01 69 35 69 62 >> >> >> >> >> >> >> >> -- >> benh~ >> >> >> >