Skip Menu |

This queue is for tickets about the Class-Std CPAN distribution.

Report information
The Basics
Id: 13943
Status: resolved
Priority: 0/
Queue: Class-Std

People
Owner: Nobody in particular
Requestors: dan.kubb-cpan [...] autopilotmarketing.com
Cc:
AdminCc:

Bug Information
Severity: Wishlist
Broken in: 0.0.2
Fixed in: (no value)



Subject: Default values other than a scalar
It would be nice to be able to specify a default value as something other than a scalar. In my particular case I wanted to be able to specify an array-ref as the default value like this: my %customers_of : ATTR( :init_arg<customers> :get<customers> :default<[]> );
Date: Mon, 01 Aug 2005 16:31:08 -0700
From: Damian Conway <damian [...] conway.org>
To: bug-Class-Std [...] rt.cpan.org
Subject: Re: [cpan #13943] Default values other than a scalar
RT-Send-Cc:
Show quoted text
> It would be nice to be able to specify a default value as something other than a scalar. > > In my particular case I wanted to be able to specify an array-ref as the default value like this: > > my %customers_of : ATTR( :init_arg<customers> :get<customers> :default<[]> ); >
Great idea. Now at the top of my ToDo list (but almost certainly delayed until after OSCON %-) Thanks.
From: dan.kubb-cpan [...] autopilotmarketing.com
Attached is a patch that allows other perl data to be used as a default value for an attribute besides scalars.
diff -ru lib/Class/Std.pm~ lib/Class/Std.pm --- lib/Class/Std.pm~ 2005-08-01 18:19:20.000000000 -0700 +++ lib/Class/Std.pm 2005-08-01 17:56:27.000000000 -0700 @@ -343,7 +343,12 @@ } # Or use default value specified... - $attr_ref->{ref}{$new_obj_id} = $attr_ref->{default}; + $attr_ref->{ref}{$new_obj_id} = eval $attr_ref->{default}; + + if ($@) { + $attr_ref->{ref}{$new_obj_id} = $attr_ref->{default}; + } + next INIT if defined $attr_ref->{ref}{$new_obj_id}; if (defined $attr_ref->{init_arg}) { @@ -1379,6 +1384,10 @@ # No BUILD() required +Note that any valid perl datatype can be used for the default +value: + + my %customers_of :ATTR( :default([]) ); =item C<< :ATTR( :get<name> ) >> diff -ru t/simple.t~ t/simple.t --- t/simple.t~ 2005-05-15 20:58:24.000000000 -0700 +++ t/simple.t 2005-08-01 18:20:15.000000000 -0700 @@ -1,13 +1,20 @@ -use Test::More 'no_plan'; +use Test::More tests => 48; package MyBase; use Class::Std; { - my %name : ATTR( :init_arg<name> :get<name> ); - my %rank : ATTR( init_arg => 'rank' :get<rank> :set<rank> ); - my %snum : ATTR( :init_arg('snum') :get<snum> ); - my %priv : ATTR; - my %def : ATTR( :default<MyBase::def> :get<default> ); + my %name : ATTR( :init_arg<name> :get<name> ); + my %rank : ATTR( init_arg => 'rank' :get<rank> :set<rank> ); + my %snum : ATTR( :init_arg('snum') :get<snum> ); + my %priv : ATTR; + my %def : ATTR( :default<MyBase::def> :get<default> ); + my %scalar : ATTR( :default<\""> ); + my %array : ATTR( :default<[]> ); + my %hash : ATTR( :default<{}> ); + my %code : ATTR( :default<sub {}> ); + my %ref : ATTR( :default<\\*glob> ); + my %glob : ATTR( :default<\*glob> ); + my %regexp : ATTR( :default<qr//> ); sub BUILD { my ($self, $ident, $arg_ref) = @_; @@ -37,6 +44,14 @@ ::is $snum{$ident}, 'MyBase::snum!' => 'MyBase::snum initialized'; ::is $priv{$ident}, 'MyBase::priv' => 'MyBase::name initialized'; ::is $def{$ident}, 'MyBase::def' => 'MyBase::def initialized'; + + ::is ref $scalar{$ident}, 'SCALAR' => 'MyBase::scalar initialized'; + ::is ref $array{$ident}, 'ARRAY' => 'MyBase::array initialized'; + ::is ref $hash{$ident}, 'HASH' => 'MyBase::hash initialized'; + ::is ref $code{$ident}, 'CODE' => 'MyBase::code initialized'; + ::is ref $ref{$ident}, 'REF' => 'MyBase::ref initialized'; + ::is ref $glob{$ident}, 'GLOB' => 'MyBase::glob initialized'; + ::is ref $regexp{$ident}, 'Regexp' => 'MyBase::regexp initialized'; } }
From: dan.kubb-cpan [...] autopilotmarketing.com
Attached is one final patch that should be applied after the others in this bug. I performed extensive testing using the Class::Std and my own live classes and uncovered one bug in the code I submitted (I wasn't checking the value's definedness before evaling), as well as one issue with Class::Std's default behaviour: I have an attribute I want to be able to specify in my new() constructor. If its not supplied its no big deal, because its optional. However, because I made an init_arg for it, Class::Std will croak if I don't pass it in. The solution I made was to specify "default<undef>", which is now possible thanks to my eval patch. I think this demonstrates my expectation that if the value isn't passed in through the init_args I want it to be undefined. However this didn't work, because since the code checks the value's defined'ness it will die. The solution that I came up with was to make Class::Std's init_args not croak if a default value was explicitly set .. to any value, even undef.
--- Std.pm 2005-08-01 21:55:44.000000000 -0700 +++ /usr/local/lib/perl5/site_perl/5.9.2/Class/Std.pm 2005-08-01 22:13:44.000000000 -0700 @@ -342,15 +342,19 @@ } - # Or use default value specified... - $attr_ref->{ref}{$new_obj_id} = eval $attr_ref->{default}; + if ( exists $attr_ref->{default} ) { + if ( defined $attr_ref->{default} ) { + # Or use default value specified... + $attr_ref->{ref}{$new_obj_id} = eval $attr_ref->{default}; + + if ($@) { + $attr_ref->{ref}{$new_obj_id} = $attr_ref->{default}; + } + } - if ($@) { - $attr_ref->{ref}{$new_obj_id} = $attr_ref->{default}; + next INIT; } - next INIT if defined $attr_ref->{ref}{$new_obj_id}; - if (defined $attr_ref->{init_arg}) { # Record missing init_arg... push @missing_inits,
Hello, Could you submit a single version of these changes with tests as per 0.0.9s: http://search.cpan.org/~dmuey/Class-Std- 0.0.9/lib/Class/Std.pm#I_know_we're_all_busy,_I'd_like_to_help_maintain_Class::Std! thanks!!
On Tue Mar 25 23:26:25 2008, DMUEY wrote: Show quoted text
> Hello, > > Could you submit a single version of these changes with tests as per > 0.0.9s: > > http://search.cpan.org/~dmuey/Class-Std- > 0.0.9/lib/Class/Std.pm#I_know_we're_all_busy,_I'd_like_to_help_maintain_Class::Std! > > thanks!!
Now that I look at it again, its already applied :) thanks!