develooper Front page | perl.perl5.porters | Postings from July 2020

Re: PERL_PERTURB_KEYS=2

Thread Previous | Thread Next
From:
hv
Date:
July 31, 2020 17:14
Subject:
Re: PERL_PERTURB_KEYS=2
Message ID:
202007311632.06VGWDP12060@crypt.org
Earler I wrote:
:demerphq <demerphq@gmail.com> wrote:
::Did you post the code that was unexpectedly non-deterministic? Maybe i
::got confused.
:
:Not yet, I've been working on cutting down the testcase to the point I
:can do so.

Below is as short as I've got it so far; very minor changes (eg replacing
the last Axiom::Dict->new call with C< bless [ {}, [] ], 'Axiom::Dict' >,
or removing C<use strict>) are enough to make the indeterminacy disappear.
I suspect something to do with class/object management in perl may be
triggering the indeterminacy.

I'm saving the below as 'axiom', and testing it for a given hash seed like so:

% PERL_PERTURB_KEYS=2 perl -wle 'local $ENV{PERL_HASH_SEED} = shift; ++$s{`./axiom`} for 1 .. 100; print "$_ $s{$_}" for sort keys %s' 1
aa 13
ab 87
% PERL_PERTURB_KEYS=2 perl -wle 'local $ENV{PERL_HASH_SEED} = shift; ++$s{`./axiom`} for 1 .. 100; print "$_ $s{$_}" for sort keys %s' 2
aa 10
ab 90
% PERL_PERTURB_KEYS=2 perl -wle 'local $ENV{PERL_HASH_SEED} = shift; ++$s{`./axiom`} for 1 .. 100; print "$_ $s{$_}" for sort keys %s' 3
bb 100
% 

Here the first two hash seeds show indeterminacy: some runs of the program
result in the two copy() calls seeing C< keys %$dict > in the order (a, b)
both times, other runs see (a, b) the first time and (b, a) the second.

The third hash seed sees (b, a) both times consistently, so it appears to
be acting deterministically.

My understanding of PERL_PERTURB_KEYS=2 is that those first two cases
should not happen - we should get the same results on each run of the
program for a given hash seed.

Hugo
---
#!/opt/v5.32.0-d/bin/perl
use strict;
use warnings;

my $dict = bless [ {}, [] ], 'Axiom::Dict';
{   
    my $sdict = bless [ {}, [] ], 'Axiom::Dict';
    $sdict->[1] = $dict->[1];
    $sdict->[0]{'a'} = $sdict->[1][0] = [];
    $sdict->[0]{'b'} = $sdict->[1][1] = [];
    my $dsdict = $sdict->copy;
    $dsdict->clone;
}

$dict->[0]{'a'} = $dict->[1][2] = [];
$dict->[0]{'b'} = $dict->[1][3] = [];
$dict->copy;
exit 0;

package Axiom::Dict {
    sub new {
        my($class) = @_;
        return bless [ {}, [] ], 'Axiom::Dict';
    }
    sub dict { shift->[0] }
    sub bind { shift->[1] }

    sub clone {
        my($other) = @_;
        my $self = bless [ {}, [] ], 'Axiom::Dict';
        my($sd, $sb) = @$self;
        my($od, $ob) = @$other;
        my %tr;
        @$sb = map { $tr{$_} = [] } @$ob;
        for my $name (keys %$od) {
            $sd->{$name} = $tr{$od->{$name}} // $od->{$name};
        }
        return $self;
    }

    sub copy {
        my($self) = @_;
        my($dict, $bind) = @$self;
        my $copy = ref($self)->new;
my $first;
        for my $name (keys %$dict) {
print $name unless $first++;
            my $bound = [];
            push @{ $copy->[1] }, $bound;
            $copy->[0]->{$name} = $bound;
        }
        return $copy;
    }
};
__END__

Thread Previous | Thread Next


nntp.perl.org: Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at ask@perl.org | Group listing | About