Re: Multiple coercions ?
I apologize, I don't mean any offense by "newbie". It was not my intent to label you that way. I was only referring to the category of questions that are easy to resolve. In regards to Moose, I consider myself a newbie, as opposed to the "experts" who created it and contribute to it. Thanks, Charles Alderman - Original Message - From: Alexis Sukrieh <[EMAIL PROTECTED]> Sent: Wed, 24 Sep 2008 17:41:02 +0200 Re: Re: Multiple coercions ? Charles Alderman a écrit : Perhaps if a user happens to overlook the version they're running before asking a question, it could be accepted as a newbie question in a moose-users list conversation. It's really funny how you can be flagged "newbie" at the first mistake you make. Indeed, I totally forgot that Moose grows so quickly that my fresh _stable_ Ubuntu system would be far too old for a bug-proof version of Moose. Indeed, this is my fault. I apology for that. But please don't start to judge people with the first email/mistake you see from them. You don't want to do that. Alexis.
Re: Multiple coercions ?
Meta questions: Is the purpose of this list to only report bugs or discuss design questions? Or is it to help out Moose users? Should the list be split into moose-dev and moose-users? Perhaps if a user happens to overlook the version they're running before asking a question, it could be accepted as a newbie question in a moose-users list conversation. Thanks, Charles Alderman - Original Message - From: Dave Rolsky <[EMAIL PROTECTED]> Sent: Wed, 24 Sep 2008 10:14:49 -0500 (CDT) Re: Re: Multiple coercions ? Ok, Moose _0.58_ was just released, and you're reporting bugs in 0.31, which was released approximately 10 months ago? Why? -dave /*== VegGuide.Org Your guide to all that's veg ==*/
Re: Multiple coercions ?
I tried running that code. My output: % perl multiple_coercions.t ok 1 - date set to 2008-09-12 ok 2 - coerce date_time from date ok 3 - date_time correctly coerced ok 4 - coerce from Int 1..4 Also: % perl -Moose -e"print $Moose::VERSION" 0.54 Thanks, Charles Alderman - Original Message - From: Alexis Sukrieh <[EMAIL PROTECTED]> Sent: Wed, 24 Sep 2008 16:57:11 +0200 Re: Re: Multiple coercions ? Alexis Sukrieh a écrit : Find attached the test script: Hmm, sorry, looks like the attachment gets droped by the ML. Here is the pure paste: $ cat multiple_coercions.t use Test::More 'no_plan'; use strict; use warnings; sub time_to_datetime($) { my $time = shift; my ($sec, $min, $hour, $day, $mon, $year) = localtime($time); $mon++; $year += 1900; $sec = sprintf('%02d', $sec); $min = sprintf('%02d', $min); $hour = sprintf('%02d', $hour); $mon = sprintf('%02d', $mon); $day = sprintf('%02d', $day); return "${year}-${mon}-${day} ${hour}:${min}:${sec}"; } # Types & Coercions use Moose::Util::TypeConstraints; subtype 'Date' => as 'Str' => where { /^\d\d\d\d-\d\d-\d\d$/ }; subtype 'DateTime' => as 'Str' => where { /^\d\d\d\d-\d\d-\d\d \d\d:\d\d:\d\d$/ }; coerce 'DateTime' => from 'Int' => via { time_to_datetime($_) }; coerce 'DateTime' => from 'Date' => via { "$_ 00:00:00" }; { package Foo; use Moose; has 'date' => ( is => 'rw', isa => 'Date', ); has 'date_time' => ( is => 'rw', isa => 'DateTime', coerce => 1, ); } # fixtures my $date = '2008-09-12'; my $date_time = '2008-09-12 00:00:00'; my $o = Foo->new; is( $date, $o->date($date), "date set to $date" ); ok( $o->date_time($o->date), 'coerce date_time from date' ); is( $date_time, $o->date_time, 'date_time correctly coerced' ); ok( $o->date_time( time ), 'coerce from Int' );
Re: Multiple coercions ?
Now - and that's where the issue gets in the scene - if I add another coercion for the DateTime subtype, but from another source, it won't work : Are you sure you haven't defined the coercion to "DateTime" from "Int" somewhere else? This works for me: { package Foo; use Moose; use Moose::Util::TypeConstraints; subtype 'Date' => as 'Str' => where { /^\d\d\d\d-\d\d-\d\d$/ }; subtype 'DateTime' => as 'Str' => where { /^\d\d\d\d-\d\d-\d\d \d\d:\d\d:\d\d$/ }; coerce 'DateTime' => from 'Date' => via { "$_ 00:00:00" }; coerce 'DateTime' => from 'Int' => via { '2008-09-24 00:00:00' }; has 'date' => ( is => 'rw', isa => 'Date', ); has 'date_time' => ( is => 'rw', isa => 'DateTime', coerce => 1, ); } { my $f = Foo->new; $f->date_time(1234); $f->date_time('2008-09-24'); } Thanks, Charles Alderman
Re: Coercions and custom type parameters
- Original Message - From: Yuval Kogman <[EMAIL PROTECTED]> Sent: Thu, 24 Jul 2008 23:27:11 +0300 Re: Re: Coercions and custom type parameters Declaring an attribute with a parameterized type: has foo => ( isa => "ArrayRef[Foo]", coerce => 1, ); has a specific behavior right now, it enables only the coercions on the type "ArrayRef[Foo]". OK, I hadn't thought about it that way. So, I can declare a subtype that looks parametrized, but it really isn't. subtype 'ArrayRef[Int]' => as 'Str' => where { 1 }; Custom parametrized types could still make sense though: MyCustomType[Foo] is a useful construct for custom container types, for functors, etc etc, so deep_coerce *is* a useful property to have Wow, I didn't know that was possible either. You guys have thought of everything... So, this is my custom collection, which is parameterizable: subtype 'BigArrayRef' => as 'ArrayRef' => where { scalar(@$_) > 1 }; has 'my_big_arrayref' => ( is => 'rw', isa => 'BigArrayRef[Int]' ); Now, I can also create a pseudo parameterizable subtype, that does something like this: subtype 'BigArrayRef[Int] => as 'ArrayRef' => where { my $ar = $_; return unless scalar( @$ar ) > 1; for ( @$ar ) { return unless m/^ \d+ $/x; } return 1; } Well what does this mean now: has 'my_new_big_arrayref' => ( is => 'rw', isa => 'BigArrayRef[Int][Int]' ); I think I've just confused myself. I'm going to sit down and play with this some more... Thanks, Charles Alderman
Re: Coercions and custom type parameters
I guess that if you're trying to prevent this as an action at a distance, 'deep_coerce' wouldn't really be acceptable either. Wouldn't that just be a more explicit warning of an action at a distance? If moose type constraints become too complicated, I guess at some point, a designer/developer just needs to turn the parametrized type into its own class. So, maybe I'm answering my own question here. At any rate, I'll look more at the mailing list archives... Thanks, Charles Alderman - Original Message - From: Yuval Kogman <[EMAIL PROTECTED]> Sent: Thu, 24 Jul 2008 22:37:45 +0300 Re: Re: Coercions and custom type parameters This has been brought up before, the short story is 'coerce => 1' may introduce action at a distance, so we decided that if at all this should be 'deep_coerce => 1'. At any rate, this is a little trickier than it sounds, but if Stevan approves deep_coerce => 1 feel free to commit this as a todo test and start hacking away. Regards, Yuval On Thu, Jul 24, 2008 at 15:20:13 -0400, Charles Alderman wrote: Hello Moose, I guess I have an enhancement idea/request. I have a parametrized ArrayRef[] of a custom type, I'd like my coercion on that type to work for any of the values in the collection. HashRef[]s should work too. Maybe Maybe[]s, but not in my example below. Would this be worthwhile or viable? If so, I'd be willing to attempt a patch... Thanks, Charles Alderman Here's a test: #!/usr/bin/perl use strict; use warnings; use Test::More tests => 2; use Test::Exception; { package Foo; use Moose; use Moose::Util::TypeConstraints; enum 'Foo::Values' => qw{ Foo Bar Baz None }; coerce 'Foo::Values' => from 'Undef' => via { 'None' }; has 'array_of_foo' => ( is => 'rw', isa=> 'ArrayRef[Foo::Values]', coerce => 1, ); } { my $foo = Foo->new(); my @ok_values = ( 'Foo', 'Bar', 'Baz', 'None' ); my @coerced_values = ( 'Foo', 'Bar', undef, 'None' ); lives_ok { $foo->array_of_foo( [EMAIL PROTECTED] ); } '... setting array with ok values'; lives_ok { $foo->array_of_foo( [EMAIL PROTECTED] ); } '... setting array with coerced values'; } -- Yuval Kogman <[EMAIL PROTECTED]> http://nothingmuch.woobling.org 0xEBD27418
Coercions and custom type parameters
Hello Moose, I guess I have an enhancement idea/request. I have a parametrized ArrayRef[] of a custom type, I'd like my coercion on that type to work for any of the values in the collection. HashRef[]s should work too. Maybe Maybe[]s, but not in my example below. Would this be worthwhile or viable? If so, I'd be willing to attempt a patch... Thanks, Charles Alderman Here's a test: #!/usr/bin/perl use strict; use warnings; use Test::More tests => 2; use Test::Exception; { package Foo; use Moose; use Moose::Util::TypeConstraints; enum 'Foo::Values' => qw{ Foo Bar Baz None }; coerce 'Foo::Values' => from 'Undef' => via { 'None' }; has 'array_of_foo' => ( is => 'rw', isa=> 'ArrayRef[Foo::Values]', coerce => 1, ); } { my $foo = Foo->new(); my @ok_values = ( 'Foo', 'Bar', 'Baz', 'None' ); my @coerced_values = ( 'Foo', 'Bar', undef, 'None' ); lives_ok { $foo->array_of_foo( [EMAIL PROTECTED] ); } '... setting array with ok values'; lives_ok { $foo->array_of_foo( [EMAIL PROTECTED] ); } '... setting array with coerced values'; }
Re: checking consistency between attributes
Speaking of triggers, why can't the trigger of an attribute be changed in an extended attribute? Like so: has '+foo' => ( trigger => sub {} ); The docs only say the "feature is restricted somewhat, so as to try and force at least some sanity into it. You are only allowed to change the following attributes: [a list not including trigger]." Would it be as easy as adding "trigger" to Moose::Meta::Attribute::legal_options_for_inheritance()? (I tried that, and it worked initially. Am I missing some un-intended side-effects somewhere?) I guess there would be some screwiness (undecided behavior) in Sartak's plan for the method-modifier-like triggers? Thusly: package Foo; use Moose; has 'foo' => ( is => 'rw', trigger => { before => sub{} } ); package Foo::Bar; use Moose; extends 'Foo'; +has 'foo' => ( trigger => { after => sub{} } ); Would foo trigger before AND after now? Thanks, Charles Alderman - Original Message - From: Stevan Little <[EMAIL PROTECTED]> Sent: Tue, 15 Jul 2008 23:05:32 -0400 Re: Re: checking consistency between attributes Ohh, I like this, very clean and re-using existing documentation :P It keeps it away from the type system too, which while it feels kinda sexy to integrate it with, it also feels wrong (not the good wrong, but the bad wrong). Sartak++ very very *very* well volunteered :) - Stevan On Jul 15, 2008, at 9:05 PM, Chris Prather wrote: On Tue, 15 Jul 2008 20:55:44 -0400, Sartak wrote: On Tue, Jul 15, 2008 at 8:29 PM, Stevan Little <[EMAIL PROTECTED]> wrote: trigger => { before => sub { ... }, after => sub { ... }, } +1 awesome 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: We already have something vaguely like this: method modifiers! Modeling multi-phase triggers after method modifiers would decrease cognitive load. - do we make the "before" trigger return a value for us to assign? No. The return value is discarded. - do we make the "before" trigger actually do the assignment? No. The before trigger is only there to perform additional validation or to call extra methods. We could have an "around" trigger which *does* wrap the assignment. - what happens if an exception is thrown inside the "before", do we catch it? No. Exceptions are generally outside of the scope of Moose. We only throw them. :) Besides, before could be used mostly for exceptions, to do multi-value validation. - how would you/should you be able to -- indicate failure or some kind in before? Throw an error. This is what we do and expect practically everywhere else, right? I second continuing the method modifier theme into triggers here. Sartak hits the nail on the head, before/after/around are nicely extended into this realm too. Keeping the theme means less confusion when it comes time to document/explain this to people who are ... shall we be kind and say intermediate moose users ... cause this is getting well into the advanced realm. Well volunteered Sartak! -Chris
Re: checking consistency between attributes
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
Re: attribute w/ coerce and trigger - trigger arguments
Thanks Stevan, I'm impressed by the quick turnaround, and I look forward to trying out the new release. Charles Alderman aldermania.com - Original Message - From: Stevan Little <[EMAIL PROTECTED]> Sent: Sat, 12 Apr 2008 23:55:24 -0400 Re: Re: attribute w/ coerce and trigger - trigger arguments Charles, This bug has been fixed in svn (http://code2.0beta.co.uk/moose/svn/Moose/trunk/) and will be in the next release (coming soon, probably this week sometime). - Stevan On Apr 9, 2008, at 2:40 PM, Charles Alderman wrote: Hello, Just started using Moose (love it). I recently spent a little time struggling through an issue with trigger arguments for a coerced attribute. So, I thought I'd post what I found here in case anyone else runs into it. Actually, I'm not sure if I found an undocumented feature of Moose, or if it's a bug. The docs say that a trigger is passed an updated value of the attribute. What happens is that if the attribute has a coercion, the argument passed to the trigger hasn't been coerced. So, technically, the argument isn't an updated value. (At least, that's where my confusion came from.) The coerced value is still available to the trigger through the attribute's accessor, so maybe having the non-coerced value also available is for the best. For clarification, I included an example. Thanks, Charles Alderman aldermania.com Versions: Moose - 0.40 Class::MOP - 0.54 -- From the Moose perldoc: The trigger option is a CODE reference which will be called after the value of the attribute is set. The CODE ref will be passed the instance itself, the **updated value** and the attribute meta-object (this is for more advanced fiddling and can typically be ignored). -- Here's an example: #This example is based on: Schwartz, R.L. "The Moose is Flying (part 2)". LinuxMag Column 95 (Jul 2007) package Mortgage; use Moose; use Moose::Util::TypeConstraints; use DateTime; use DateTime::Format::DateManip; use Date::Manip; Date_Init( 'TZ=US/Eastern' ); subtype 'DateTime' => as 'Object' => where { $_->isa('DateTime') }; coerce 'DateTime' => from 'Str' => via { DateTime::Format::DateManip->parse_datetime($_) } => from 'HashRef' => via { DateTime->new(%$_) }; has 'closing_date' => ( is => 'rw', isa => 'DateTime', coerce => 1, trigger => sub { my ( $self, $val, $meta ) = @_; print $self->closing_date->isa('DateTime') ? 'yes' : 'no'; # yes print $val->isa('DateTime')? 'yes' : 'no'; # no??? } ); 1; package main; my $mtg = Mortgage->new( closing_date => 'yesterday' ); print $mtg->closing_date->isa('DateTime') ? 'yes' : 'no'; # yes
attribute w/ coerce and trigger - trigger arguments
Hello, Just started using Moose (love it). I recently spent a little time struggling through an issue with trigger arguments for a coerced attribute. So, I thought I'd post what I found here in case anyone else runs into it. Actually, I'm not sure if I found an undocumented feature of Moose, or if it's a bug. The docs say that a trigger is passed an updated value of the attribute. What happens is that if the attribute has a coercion, the argument passed to the trigger hasn't been coerced. So, technically, the argument isn't an updated value. (At least, that's where my confusion came from.) The coerced value is still available to the trigger through the attribute's accessor, so maybe having the non-coerced value also available is for the best. For clarification, I included an example. Thanks, Charles Alderman aldermania.com Versions: Moose - 0.40 Class::MOP - 0.54 -- From the Moose perldoc: The trigger option is a CODE reference which will be called after the value of the attribute is set. The CODE ref will be passed the instance itself, the **updated value** and the attribute meta-object (this is for more advanced fiddling and can typically be ignored). -- Here's an example: #This example is based on: Schwartz, R.L. "The Moose is Flying (part 2)". LinuxMag Column 95 (Jul 2007) package Mortgage; use Moose; use Moose::Util::TypeConstraints; use DateTime; use DateTime::Format::DateManip; use Date::Manip; Date_Init( 'TZ=US/Eastern' ); subtype 'DateTime' => as 'Object' => where { $_->isa('DateTime') }; coerce 'DateTime' => from 'Str' => via { DateTime::Format::DateManip->parse_datetime($_) } => from 'HashRef' => via { DateTime->new(%$_) }; has 'closing_date' => ( is => 'rw', isa => 'DateTime', coerce => 1, trigger => sub { my ( $self, $val, $meta ) = @_; print $self->closing_date->isa('DateTime') ? 'yes' : 'no'; # yes print $val->isa('DateTime')? 'yes' : 'no'; # no??? } ); 1; package main; my $mtg = Mortgage->new( closing_date => 'yesterday' ); print $mtg->closing_date->isa('DateTime') ? 'yes' : 'no'; # yes