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~
>>
>>
>>
>

Reply via email to