On 3/23/2011 8:59 AM, Chad Davis wrote:
This seems to be a bug, but I'm hoping that someone that understand
Storable better than I can shed some light on this. I checked the list
archives and didn't find any discussions on this specific issue.

I use Storable, which is implemented for piddles with
PDL::IO::Storable, to serialize to files. I also use Storable::dclone
in certain algorithms that need to clone data structures that
(sometimes) contain piddles. dclone (deep clone) fails to make a deep
clone of piddles, though. This breaks the documented semantics of
Storable, that dclone(.) == thaw(freeze(.))


I took a look at the Storable documentation and came across
this:

Any class may define hooks that will be called during the serialization
and deserialization process on objects that are instances of that
class.  Those hooks can redefine the way serialization is performed
(and therefore, how the symmetrical deserialization should be
conducted).

Since we said earlier:

    dclone(.) = thaw(freeze(.))

everything we say about hooks should also hold for deep cloning.
However, hooks get to know whether the operation is a mere
serialization, or a cloning.

Therefore, when serializing hooks are involved,

    dclone(.) <> thaw(freeze(.))

Well, you could keep them in sync, but there's no guarantee it will
always hold on classes somebody else wrote.  Besides, there is little
to gain in doing so: a serializing hook could keep only one attribute
of an object, which is probably not what should happen during a deep
cloning of that same object.

so it appears that keeping the identity is not required
but would seem to obey the principle of lease surprise.
It seems like applying this patch would be reasonable
but I'd like to hear any other thoughts (Christian?).

--Chris

I tested this on the development release just announced
(PDL-2.4.7_013), by adding a couple tests to ./t/storable.t (patch
attached), like this:


# Test that freeze + thaw results in new object
$seq1 = sequence(3);
$seq1_tf = thaw(freeze($seq1));
$seq1->slice('1') .= 9;
ok(! all($seq1 == $seq1_tf), 'Initialization from seraialized object') or
     diag($seq1, $seq1_tf);

# Test that dclone results in a new object
# i.e. that dclone(.) == thaw(freeze(.))
$seq2 = sequence(4);
$seq2_dc = Storable::dclone($seq2);
$seq2->slice('2') .= 8;
ok(! all($seq2 == $seq2_dc), 'Initialization from dclone object') or
     diag($seq2, $seq2_dc);


The first test thaw(freeze(.)) passes, but the dclone(.) test does
not. This is because PDL::IO::Storable has a 'return if $cloning' both
in STORABLE_freeze() and STORABLE_thaw(). Presumably, this is where
I'm looking for some feedback, this is to allow Perl to do it's own
(efficient) cloning, rather than serialize and deserialize potentially
large objects. This doesn't work for piddles, though. It just results
in the Perl data structure being cloned, while the underlying piddle
data points to the original memory. I.e. modifying the clone then
modifies the original. Since $cloning is not 'true' during a
serialization, I removed the 'return if $cloning' from both functions
(patch attached). This doesn't, I believe, change standard
serialization or deserialization, but it does make cloning via dclone
possible. Of course, there are probably more efficient ways of cloning
a piddle, but it does now conform to the Storable inferface. I
verified that all tests still pass with this patch. (I didn't compile
with PDL::FFTW or Proj4 however).

I've been using this modified PDL::IO::Storable successfully for quite
a while, but wanted to mention it finally, having seen the
announcements of the new dev release.

Cheers,
Chad

_______________________________________________
Perldl mailing list
[email protected]
http://mailman.jach.hawaii.edu/mailman/listinfo/perldl

Reply via email to