Subject: | Reversed logic on overload::StrVal() in AdjacencyMap::Vertex::__set_path |
I am on perl, v5.10.0 built for i486-linux-gnu-thread-multi using Graph 0.91
I was using the Bio::Network::ProteinNet (1.006), which extends your
Graph module, with Storable (2.18) when I ran into problems using
Storable::retrieve. The deserialised Graph instances reported no
neighbors() on any nodes.
I traced this back to the 'refvertexed' option. I was using this option,
because my nodes are objects and the Graph documentation suggested that
this is the proper way to do things. My node objects use overload, to
provide stringification.
Running through the debugger, I found that refvertexed=>1 results in
using Graph::AdjacencyMap::Vertex whereas refvertexed=>0 results in
using Graph::AdjacencyMap::Light. The G::A::Light calls my overloaded ""
on my node objects, whereas the G::A::Vertex does not call my overloaded
"" on my node objects.
I inspected G::A::Vertex and found on line 37 (and 78) in version 0.91:
my $q = ref $k && ($f & _REF) && overload::Method($k, '""') ?
overload::StrVal($k) : $k;
I believe this logic to be reversed from what you seem to intend. The
overload::StrVal() uses Perl's builtin stringification, providing
something like MyNode=HASH(0x972e240) and ignores the stringification I
have implemented in my MyNode class. This was the reason e.g.
Graph::neighbors() was no longer working after Storable::retrieve(),
because the constructed graph object had indexed the nodes by the memory
address that they had before they were serialized with Storable::store.
I believe the intent is simply:
my $q = ref $k && ($f & _REF) && ! overload::Method($k, '""') ?
overload::StrVal($k) : $k;
... which would use the objects own stringification, when present,
otherwise using Perl's generic stringification of hash references. This
is all the attached patch contains. See the script for an example use
case. It doesn't use Storable, but it just shows that the node keys in
the graph are different when G::A::Vertex is used (via refvertexed=>1),
though the node objects provide an overloaded "" in any case.
Cheers,
Chad
Subject: | retrieveVertex.pl |
#!/usr/bin/env perl
use strict;
use warnings;
use Graph;
use Storable;
use Test::More 'no_plan';
use Data::Dumper;
use Carp qw/cluck/;
package MyNode;
use overload ('""' => '_asstring', fallback=>1);
sub new {
my ($class, %ops) = @_;
return bless { %ops }, $class;
}
sub _asstring {
my ($self) = @_;
my $str = $self->{'name'};
Carp::cluck("Stringifying $str");
return $self->{'name'};
}
1;
package main;
my $gnoref = new Graph;
my $gwithref = new Graph(refvertexed=>1);
my $n1 = new MyNode('name'=>'alpha');
my $n2 = new MyNode('name'=>'beta');
$gnoref->add_edge($n1, $n2);
# If you see no further stack traces from cluck, then :
print "\nNo more stringification occurs after this point\n\n";
$gwithref->add_edge($n1, $n2);
# And then this fails, meaning that Storable is also not usable, because the
# nodes are hashed by their memory addresses, which will change on retrieve()
is_deeply([sort keys %{$gnoref->[2]->[4]}],[sort keys %{$gwithref->[2]->[4]}]);
print "\n";
__END__
Subject: | Vertex.diff |
--- Vertex.pm.bak 2009-02-24 14:04:57.000000000 +0100
+++ Vertex.pm 2009-02-24 14:06:14.000000000 +0100
@@ -34,7 +34,7 @@
my @p = $p;
my @k;
my $k = shift;
- my $q = ref $k && ($f & _REF) && overload::Method($k, '""') ? overload::StrVal($k) : $k;
+ my $q = ref $k && ($f & _REF) && ! overload::Method($k, '""') ? overload::StrVal($k) : $k;
push @k, $q;
return (\@p, \@k);
}
@@ -75,7 +75,7 @@
my @p = $p;
my @k;
my $k = shift;
- my $q = ref $k && ($f & _REF) && overload::Method($k, '""') ? overload::StrVal($k) : $k;
+ my $q = ref $k && ($f & _REF) && ! overload::Method($k, '""') ? overload::StrVal($k) : $k;
push @k, $q;
return (\@p, \@k);
}