Orignal - Very simple properties/attributes/fields for Perl
package house; use parent qw(Orignal); house->attributes({SCALARS =>[qw(address style type)], ORDERED_HASHES =>[qw(owners)], HASHES =>[qw(rooms)], ARRAYS =>[qw(occupants pets)]}); 1; use house; my $big_house = house->new({address=>'1313 Mockingbird', type =>'Mansion' style =>'Gothic' owners =>{present=>'Lily Munster',past=>'Sam Dracula',builder=>'V. Frankenstein'} rooms =>{bathrooms=>0,bedrooms=>5,playroom=>1, dungeon=>1, lab=>1}, occupants=>[qw(Herman Lilly Grandpa Eddie Marilyn)]}, pets =>[qw(Spot Kitty)]); my $address = $big_house->address(); my @people = $big_house->occupants(); my %rooms = $big_house->rooms();
When I said simple I meant very simple. It basically just gives you a very easy way to create class level attributes that encapsulate class data, enforcing unique field names and has the added bonus of an ordered hash.
Simply think of it as the base class for other classes and you got the concept. Still unclear well if you are like me and hate writing setters and getters then this is the mod for you, as this is all it does.
The main goal of Orignal is to be light and easy to use, the code is less than 20k and has no dependencies on other modules. I created it out of frustration of liking perl 5.14 attributes but being stuck with coding in perl 5.6.
Orignal should always be used as part of a larger class or module never on its own. Simply use Orignal and then call the 'attributes' method directly on your package with an attributes hash that contains the correct attribute keys.
package something; use Orignal; something->{SCALARS=>[qw(nothing)];
There are four Attribute keys SCALARS, HASHES, ORDERED_HAHSES and ARRAYS and each key if used must point to an array reference of fields. Orignal takes the fields and then creates the code references for each them that you can then use as if the code was actually in the module.
Use only when defining your package. Any other use will result in a die. For example
package house; use parent qw(Orignal); house->attributes({SCALARS =>[qw(address style type)], ORDERED_HASHES =>[qw(owners)], HASHES =>[qw(rooms)], ARRAYS =>[qw(occupants pets)]}); 1;
Will create a package called house that you can use like this
use house; my $big_house = house->new({address=>'1313 Mockingbird', type =>'Mansion' style =>'Gothic' owners =>{present=>'Lily Munster',past=>'Sam Dracula',builder=>'V. Frankenstein'} rooms =>{bathrooms=>0,bedrooms=>5,playroom=>1, dungeon=>1, lab=>1}, occupants=>[qw(Herman Lilly Grandpa Eddie Marilyn)]}, pets =>[qw(Spot Kitty)]);
This is your standard new that takes a hash ref and if a Key in that hash matches a key the name of an attribute the attribute is set to that value. If a hash ref key does not match it is simply ignored. It also does not care if you do not match all the attribute names.
my $dho_house = house->new({address=>'472 Evergreen Terrace', type =>'Small', style =>'Clapboard', owners =>{present=>'H. J. Simpson',past=>'Ned Flanders'}, pets =>[qw(snowball5,santas little helper)]);
This will return the attribute hash ref used in the creation of the class.
my $attrb = $big_house->attributes(); $attrb would point to this hash {SCALARS =>['address','style','type'], ORDERED_HASHES =>['owners'], HASHES =>['rooms'], ARRAYS =>['occupants','pets']}
Simple Perl scalars.
A plerlish getter for these that uses the field name.
print $big_house->address();
Will return the value stored in 'address' attribute;
A simple perlish setter that uses the field name.
$big_house->address('472 Evergreen Terrace');
Will set the value of the 'address' attribute to '472 Evergreen Terrace';
You can add an optional validator sub to a SCALAR attribute. You can validate any condition you want but you will have to follow this design pattern ATTRIBUTE_NAME_validate for the sub name, a shift to get the class, then the @_ to get the values passed into to validation sub from the setter, Finally use die if you fail validation. See the examples below;
#address must not be undef sub address_validate { my $self = shift; my ($new_address) = @_; die("ERROR: SomeMode::House::address, cannot be empty.") unless ($new_address); } #address cannot be "NO" sub address_validate { my $self = shift; my ($new_address) = @_; die("ERROR: SomeMode::House::address, cannot be 'NO'.") if ($new_address eq 'NO'); }
Simple Perl hashes of scalars. Orignal has two types unordered and ordered they share all the same methods.
A little more complex this time but still uses the field name.
my %some_rooms = $big_house->rooms(); my $some_rooms = $big_house->rooms();
will return the hash stored in the rooms attribute of $big_house when called in list context. In scalar context it will return the hash key pair string.
my %bath_count = $big_house->rooms('bathrooms','dungeon'); my $bath_count = $big_house->rooms('bathrooms','dungeon');
will return a hash of 2 keys and their values from the 'rooms' attribute when called in list context and in scalar context is will return the hash key pair string. If a key is not found it will return nothing.
Both the hash and ordered_hash work in the same manner.
Same as Scalar the field name but can take a hash ref as a parameter as well.
my %owners = $big_house->rooms({kitchen =>1}); my $owners = $big_house->rooms({kitchen =>1});
Will add the name values pair 'kitchen=>1' to the rooms attribute is return the new hash while in scalar context just the key pair string will be returned. When using an ordered_hash the order in which you enter the new key value pairs will be retained by Orignal except when on a new as you are passing a hash in that will not be in order.
Sending an empty hash ref to the function
$big_house->owners({})
will empty out the rooms attribute and return undef, both the hash and ordered_hash work in the same manner.
Orignal defines a delete method as well which is in the format delete_field() that works in the same manner as a normal hash delete deleting a value from a hash.
# big_house->rooms = {bathrooms=>0,bedrooms=>5,playroom=>1, dungeon=>1, lab=>1} $scalar = $big_house->delete_rooms(bedrooms); # $scalar is 5 $scalar = $big_house->delete_rooms(qw(playroom bathrooms)); # $scalar is 0 @array = $big_house->delete_rooms(qw(dungeon playroom lab)); # @array is (1,undef,1);
Orignal defines an exists method as well which is in the format exits_field() it works in the same manner as a normal hash exits, testing whether a hash key is present. It has the added bonus if you ask for more than one key it will give the total count of keys present.
# big_house->rooms = {bathrooms=>0,bedrooms=>5,playroom=>1, dungeon=>1, lab=>1} $scalar = $big_house->exists_rooms(bedrooms); # $scalar is 1 $scalar = $big_house->exists_rooms(funroom); # $scalar is 0 $array = $big_house->exists_rooms(qw(dungeon playroom lab)); # $scalar is 3
Orignal defines a keys method as well which is in the format keys_field() it works in the same manner as a normal hash keys retrieving the list of indices from a hash. However for an Ordered Hash they come out the same way they went in.
# big_house->rooms = {bathrooms=>0,bedrooms=>5,playroom=>1, dungeon=>1, lab=>1} $scalar = $big_house->keys_rooms(); # $scalar is 5 @array = $big_house->keys_rooms(); # @array is (dungeon,lab,bedrooms,playroom,bathrooms) # $big_house->owners ={present=>'Lily Munster',past=>'Sam Dracula',builder=>'V. Frankenstein'} # ordered hash $scalar = $big_house->keys_owners(); # $scalar is 3 $array = $big_house->keys_owners(); # @array is (present,past,builder)
As you can see order hash preserves the order of the keys
You can add an optional validator sub to any HASH or ORDERED_HASH attribute. You can validate any condition you want but you will have to follow this design pattern ATTRIBUTE_NAME_validate for the sub name, a shift to get the class, then the @_ to get the values passed into to validation sub from the setter, Finally use die if you fail validation. See the examples below;
#address must not be empty sub address_validate { my $self = shift; my ($new_address) = @_; die("ERROR: SomeMode::House::address, cannot be empty.") unless ($new_address); } #address has to be an must a hash ref sub address_validate { my $self = shift; my ($new_address) = @_; ref($new_address) eq 'HASH' || die("ERROR: SomeMode::House::address, must be a 'HASH' Ref."); }
Orignal defines a values method as well which is in the format values_field() it works in the same manner as a normal hash values returning a list of the values in a hash. However for an Ordered Hash they come out the same way they went in.
# big_house->rooms = {bathrooms=>0,bedrooms=>5,playroom=>1, dungeon=>1, lab=>1} $scalar = $big_house->values_rooms(); # $scalar is 5 @array = $big_house->values_rooms(); # @array is (1,0,5,1,0) # $big_house->owners ={present=>'Lily Munster',past=>'Sam Dracula',builder=>'V. Frankenstein'} # ordered hash $scalar = $big_house->values_owners(); # $scalar is 3 $array = $big_house->values_owners(); # @array is ('Lily Munster','Sam Dracula','V. Frankenstein')
As you can see order hash preserves the order of the values.
Simple Perl Arrays of scalars.
my @pets = $big_house->pets(); my $pets = $big_house->pets();
will return the array stored in the pets attribute of $big_house when called in list context. In scalar context it will return the count of indexes on the array.
my @pets = $big_house->pets(0,2); my $pets = $big_house->pets(0,2);
will return an array of 2 the values from the 'pets' attribute when called in list context and in scalar context is will return the count. If a index is off the array it will return nothing.
Same as Scalar the field name but can also take an array ref as the parameter.
my @pets = $big_house->pets(qw(Raven Igor)}); my $pets = $big_house->pets(qw(Raven Igor));
Will add the values Raven and Igor to the end of the pets attribute and return the new array if called in list context. If called in scalar context just the length of the array will be returned. Like any array values can be duplicated.
Sending an empty array ref to the method
$big_house->pets([]);
will empty out the pets attribute and return undef.
Orignal defines a pop method as well which is in the format pop_field() it works in the same manner as a normal array pop removing the last element from an array and returning it.
pets =>[qw(Spot Kitty)]) $scalar = $big_house->pop_pets(); # $scalar is Kitty @array = $big_house->pets(); # @array is ('Spot')
Orignal defines a push method as well which is in the format push_field() it works in the same manner as a normal array push appending one or more elements to an array.
pets =>[qw(Spot)]) $scalar = $big_house->push_pets('Kitty'); # $scalar is 2, pets= ('Spot','Kitty') @array = $big_house->push_pets('Kitty'); @array is ('Spot','Kitty'), pets= ('Spot','Kitty')
Orignal defines a shift method as well which is in the format shift_field() it works in the same manner as a normal array shift removing the first element of an array, and returning it .
pets =>[qw(Spot Kitty)]) $scalar = $big_house->shift_pets(); # $scalar is Spot @array = $big_house->pets(); # @array is ('Kitty')
Orignal defines a unshift method as well which is in the format unshift_field() it works in the same manner as a normal array unshift prepending more elements to the beginning of a list.
pets =>[qw(Spot)]) $scalar = $big_house->push_pets('Kitty'); # $scalar is 2, pets= ('Kitty','Spot') @array = $big_house->push_pets('Kitty'); @array is ('Kitty','Spot'), pets= ('Kitty','Spot')
You can add an optional validator sub to an ARRAY attribute. You can validate any condition you want but you will have to follow this design pattern ATTRIBUTE_NAME_validate for the sub name, a shift to get the class, then the @_ to get the values passed into to validation sub from the setter, Finally use die if you fail validation. See the examples below;
#address must not be empty sub address_validate { my $self = shift; my ($new_address) = @_; die("ERROR: SomeMode::House::address, cannot be empty.") unless ($new_address); } #address has to be an must a array ref sub address_validate { my $self = shift; my ($new_address) = @_; ref($new_address) eq 'ARRAY' || die("ERROR: SomeMode::House::address, must be an 'ARRAY' Ref."); }
I haven't found any but I am sure there are? You can report them here https://rt.cpan.org/Public/Dist/Display.html?Name=Orignal or here https://github.com/byterock/Orignal/issues.
Now there is a Wiki, but nothing there yet https://github.com/byterock/Orignal/wiki.
John Scoles.
https://github.com/byterock/Orignal
Copyright 2011 By John Scoles.
This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself.
To install Orignal, copy and paste the appropriate command in to your terminal.
cpanm
cpanm Orignal
CPAN shell
perl -MCPAN -e shell install Orignal
For more information on module installation, please visit the detailed CPAN module installation guide.