Front page | perl.moose |
Postings from July 2008
Re: checking consistency between attributes
Thread Previous
|
Thread Next
From:
Christopher Brown
Date:
July 15, 2008 18:46
Subject:
Re: checking consistency between attributes
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 <
stevan.little@iinteractive.com> 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 <
>> stevan.little@iinteractive.com> 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, charlie@aldermania.com <charlie@aldermania.com> 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 <Guillaume.Rousse@inria.fr>
>> 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~
>>
>>
>>
>
Thread Previous
|
Thread Next