NAME
Value::Diff - find the difference between two Perl values
SYNOPSIS
use Value::Diff;
use Data::Dumper;
my $left = {
key_one => [1, 2, 3],
key_two => undef,
};
my $right = {
key_one => [1, 3],
};
if (diff($left, $right, \my $out)) {
print Dumper($out);
}
# output:
$VAR1 = {
'key_one' => [2],
'key_two' => undef
};
DESCRIPTION
This module provides a routine diff
that finds out a difference between two Perl data structures.
Two first arguments order is significant - the left value is treated as the comparison base. By applying resulting difference to the right value, it will contain at least all the values the left value contains. It is possible the altered right value will end up being a superset of the left value - containing extra keys.
Supported reference types are HASH
, ARRAY
, SCALAR
and REF
. All other values are compared using string comparison, which may or may not do the right thing.
ARRAY
s are treated as sets of values - their index in the array is not taken into account, as long as matching value can be found. See "CAVEATS" for an array caveat.
EXPORTED FUNCTIONS
All functions are exported by default.
diff
my $has_diff = diff($left_value, $right_value, \$output);
This function finds out the change that has to be made to $right_value
for it to contain at least all the values $left_value
contains.
The return value of this function indicates whether $right_value
need to be changed at all. If yes, that difference is put into $output
(if passed). If no, $output
(if passed) is emptied into the empty value of the same reference type as $left_value
.
If $right_value
has more values than $left_value
they will not be included in the diff. Call the method again with switched value order and merge the results to get the full difference.
EXAMPLES
This module was initially written to allow testing data state that is built incrementally:
use Value::Diff;
use Test::More;
my $wanted_data = { ... };
sub get_messages { ... }
sub check_received
{
my ($received) = @_;
# $received contains something we didn't expect
if (diff($received, $wanted_data)) {
return 0;
}
# replace $wanted_data with the parts we haven't yet received
diff($wanted_data, $received, \$wanted_data);
return 1;
}
sub check_finished
{
# once we want nothing more, we're finished
return !%{$wanted_data};
}
foreach my $received (get_messages()) {
ok check_received($received), 'received data ok';
}
ok check_finished, 'finished ok';
done_testing;
CAVEATS
Since arrays are not treated in order but rather like a set of values, the difference in array values returned by the module is always the entire array element. It would be nice to get the smallest difference out of all array elements, but that could be very resource-intensive to find out. For the time being this behavior will stay as it is, but may be changed in the future to be more precise.
SEE ALSO
Hash::Diff is nice, but lacks the ability to handle arrays
Struct::Diff is much more complex
AUTHOR
Bartosz Jarzyna <bbrtj.pro@gmail.com>
COPYRIGHT AND LICENSE
Copyright (C) 2022 by Bartosz Jarzyna
This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself.