Re: checking consistency between attributes

[email protected] ("Christopher Brown")
Newsgroups perl.moose
Message-ID <[email protected]>
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~
>>
>>
>>
>
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.