Type::Tie::Aggregate - like Type::Tie, but slower and more flexible
version 0.001
use Type::Tie::Aggregate; use Types::Standard qw(Dict Optional Num Str); ttie my %hash, Dict[name => Str, age => Optional[Num]], ( name => 'John Doe', age => 42, ); $hash{name} = 'Jane Doe'; # ok $hash{age}++; # ok $hash{age} = 'forty-two; # dies delete $hash{name}; # dies ('name' is mandatory) # Unfortunately this does not work, because the hash is # momentarily cleared and will no longer pass the type constraint # (which requires a 'name' key). %hash = (name => 'J. Random Hacker'); # Use this instead (also more efficient). (tied %hash)->initialize(name => 'J. Random Hacker');
Like Type::Tie, this module exports a single function: ttie. Also like Type::Tie, ttie ties a variable to a type constraint (coercions will be honored).
ttie
However, unlike Type::Tie, when an assignment happens on a variable tied with ttie, the entire variable will be re-checked, not just the value that was added. This is much more expensive, of course, but can be very useful for structured types such as Dict from Types::Standard as show in the "SYNOPSIS".
Dict
Any type constraints supporting the Type::API interface should work, not just Type::Tiny types. However, in the examples that follow, all type constraints are from Types::Standard unless specified otherwise.
Since some types don't allow empty values (see the "SYNOPSIS"), values may need to be given when initializing the type. For example, this is invalid:
ttie my %hash, Dict[name => Str]; # dies
No values were given to initialize %hash, so %hash failed the type constraint Dict[name = Str]> (which requires a name key). Instead, this should be done:
%hash
Dict[name =
name
ttie my %hash, Dict[name => Str], (name => 'My Name');
This initializes %hash with the value (name => 'My Name') before any type checking is performed, so, at the end of the day, %hash passes the type constraint.
(name => 'My Name')
Another important thing to note is that when a variable is re-initialized, it is temporarily emptied. So the following is invalid:
ttie my %hash, Dict[name => Str], (name => 'My Name'); %hash = (name => 'Other Name'); # dies
Instead, the initialize method should be used on the tied object, like so:
initialize
ttie my %hash, Dict[name => Str], (name => 'My Name'); (tied %hash)->initialize(name => 'Other Name'); # ok
This is also more efficient than the previous method.
ttie ties variables deeply, meaning that if any references contained within the variable are changed, the entire variable is rechecked against the type constraint. Blessed objects are not deeply tied, but tied references are and the functionality of these tied references is preserved.
For example, the following Does The Right Thing(TM):
ttie my %hash, HashRef[ArrayRef[Int]]; $hash{foo} = [1, 2, 3]; # ok $hash{foo}[0] = 'one'; # dies $hash{bar} = [3, 2, 1]; # ok push @{$hash{bar}}, 'zero'; # dies
This also works:
use List::Util qw(all); use Tie::RefHash; ttie my @array, ArrayRef[HashRef[Int]]; my $scalar_key = 'scalar'; my @array_key = (1, 2, 3); tie my %refhash, 'Tie::RefHash', ( \$scalar_key => 1, \@array_key => 2, ); push @array, \%refhash; $array[0]{\$scalar_key} = 'foo'; # dies $array[0]{\@array_key} = 42; # ok all { ref ne '' } keys %{$array[0]}; # true
Currently, circular references are not handled correctly (see "Circular References").
ttie my $scalar, TYPE, $init_val; ttie my @array, TYPE, @init_val; ttie my %hash, TYPE, %init_val;
Tie $scalar, @array, or %hash to TYPE and initialize with $init_val, @init_val, or %init_val.
$scalar
@array
TYPE
$init_val
@init_val
%init_val
(tied $scalar)->initialize($init_val); (tied @array)->initialize(@init_val); (tied %hash)->initialize(%init_val);
Re-initialize $scalar, @array, or %hash. This is necessary because some types don't allow an empty value, and the variable will temporarily be emptied (except for scalars) if initialized the usual way (e.g., @array = qw(foo bar baz)). This is also more efficient than conventional initialization.
@array = qw(foo bar baz)
See "Initialization and Re-initialization" for more info.
my $type = (tied VAR)->type;
Return the type constraint for VAR. Note that the type cannot currently be set, only read.
VAR
Re-initialization of tied variables using @array = @init or %hash = %init does not always work. Use (tied @array)->initialize(@init) and (tied %hash)->initialize(%init) instead. See "Initialization and Re-initialization" for more information.
@array = @init
%hash = %init
(tied @array)->initialize(@init)
(tied %hash)->initialize(%init)
If a variable tied to a type contains a reference, then that reference cannot be contained by any other variable tied to a type. For example, the following will die:
my $arrayref = [42]; ttie my @num_array, ArrayRef[ArrayRef[Num]], ($arrayref); ttie my @str_array, ArrayRef[ArrayRef[Str]], ($arrayref);
If this were allowed, it would not be clear whether push @$arrayref, 'foo' should die or not. This behavior may be changed in a later release, but you probably should not be doing this regardless.
push @$arrayref, 'foo'
Circular references are not handled correctly. Hopefully this will be fixed in a future release.
Please report any bugs or feature requests on the bugtracker website https://rt.cpan.org/Public/Dist/Display.html?Name=Type-Tie-Aggregate or by email to bug-Type-Tie-Aggregate@rt.cpan.org.
When submitting a bug or request, please include a test-file or a patch to an existing test-file that illustrates the bug or desired feature.
Type::Tie
Asher Gordon <AsDaGo@posteo.net>
Copyright (C) 2021 Asher Gordon <AsDaGo@posteo.net>
This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>.
To install Type::Tie::Aggregate, copy and paste the appropriate command in to your terminal.
cpanm
cpanm Type::Tie::Aggregate
CPAN shell
perl -MCPAN -e shell install Type::Tie::Aggregate
For more information on module installation, please visit the detailed CPAN module installation guide.