У меня есть ситуация, когда я хочу создать подпись структуры данных:
my $signature = ds_to_sig(
{ foo => 'bar',
baz => 'bundy',
boing => undef,
number => 1_234_567,
}
);
Цель должна заключаться в том, чтобы при изменении структуры данных изменилась и подпись.
Есть ли устоявшийся способ сделать это?





Думаю, вы ищете слово "хеширование".
По сути, вы помещаете свою структуру данных через функцию, которая генерирует из нее довольно уникальное значение. Это значение будет вашей подписью.
Я думаю, что вы ищете хеш-функцию. Я бы порекомендовал такой подход:
use Storable;
$Storable::canonical = 1;
sub ds_to_sig {
my $structure = shift;
return hash(freeze $structure);
}
Хеш-функцией может быть любая хеш-функция, например функция md5 из Дайджест :: MD5.
Сделайте это 3 за 3 минуты! Думаю, это может означать только то, что мы все сделали правильно ;-)
Ключ там $ Storable :: canonical. Без этого Storable не гарантирует порядок элементов.
Вероятно, вам следует использовать nfreeze для согласованности между платформами
Разве вы не можете использовать объект вместо структуры? Таким образом, вы могли видеть, является ли объект экземпляром типа, без необходимости сравнивать хэши и т. д.
структуры данных и объекты в Perl 5 в значительной степени взаимозаменяемы - объекты на самом деле являются просто благословенными ссылками на данные. В любом случае - я хочу получить подпись содержимого данных
Настоящая проблема этого подхода в том, что ему нужны данные. Поскольку данные используются для поддержания состояния объектов, вам придется создавать экземпляр нового объекта каждый раз, когда состояние изменяется, тем самым сводя на нет этот подход.
Используйте Хранимый :: nstore, чтобы превратить его в двоичное представление, а затем вычислить контрольную сумму (например, с помощью модуля Digest).
Оба модуля являются базовыми модулями.
Я только что отредактировал свой код, чтобы сделать именно это. Мы с тобой снова на одном пути!
Лучший способ сделать это - использовать систему сериализации с глубокой структурой, например Хранимый. Две структуры с одинаковыми данными будут производить один и тот же большой двоичный объект вывода Storable, поэтому их можно сравнивать.
#!/usr/bin/perl
use strict;
use warnings;
use Storable ('freeze');
$Storable::canonical = 1;
my $one = { foo => 42, bar => [ 1, 2, 3 ] };
my $two = { foo => 42, bar => [ 1, 2, 3 ] };
my $one_s = freeze $one;
my $two_s = freeze $two;
print "match\n" if $one_s eq $two_s;
... И чтобы доказать обратное:
$one = [ 4, 5, 6 ];
$one_s = freeze $one;
print "no match" if $one_s ne $two_s;
Вам нужно установить $ Storable :: canonical в истинное значение. Это может не иметь значения для маленьких примеров, но важно для гораздо более крупных.
Digest::MD5->new->add(
Data::Dumper->new([$structure])
->Purity(0)
->Terse(1)
->Indent(0)
->Useqq(1)
->Sortkeys(1)
->Dump()
)->b64digest();
Хе-хе. два практически идентичных ответа менее чем за 2 минуты.