Beefy Boxes and Bandwidth Generously Provided by pair Networks
Think about Loose Coupling

Moose stringification overloading isn't working

by dd-b (Monk)
on Feb 09, 2013 at 22:05 UTC ( [id://1017992] : perlquestion . print w/replies, xml ) Need Help??

dd-b has asked for the wisdom of the Perl Monks concerning the following question:

I've got a simple case working exactly as I expect and as documented, but a more complicated case NOT working. The main difference is that in the more complicated case, I'm accessing a child class of where I did the overload.

In the parent class I do:

use overload '""' => \&_stringify; sub _stringify { my $this = shift; # Actually operator arg, NOT a "this" $this->row->ID; };

I use it like this:

$logger->trace("Zep is " . ref($zep) . " stringifies as $zep" . " but +_stringify returns " . $zep->_stringify );

The resulting log line comes out like this: 20130209 15:27:30.041 TRACE 158 6070: Zep is OT::Zeppelin::AddVendorKey stringifies as OT::Zeppelin::AddVendorKey=HASH(0x378d480) but _stringify returns OT::DB::Result::Upload|upload|upload_id=1

OT::Zeppelin::AddVendorKey is a direct child of OT::Zeppelin, which is where the operator overload was done.

My head hurts, and the wall seems to still be fine. Any ideas?

Replies are listed 'Best First'.
Re: Moose stringification overloading isn't working
by moritz (Cardinal) on Feb 10, 2013 at 09:13 UTC

    You didn't post code that would let me reproduce your problem, so I can only guess.

    One guess is that you wrote another sub _stringify in a child class, and expected it to be called by the string overloading.

    It won't, of course, because you gave overload a reference to this one subroutine. If you want that kind of polymorphism, use

    use overload '""' => sub { shift->_stringify() };

    If you don't, make sure to do an apple-to-apple comparison by writing $logger->trace("Zep is " . ref($zep) . " stringifies as $zep" . " but _stringify returns " . OT::Zeppelin::_stringify($zep) );

    You can solve any problem in computer science with another layer of indirection, except the problem of too many layers of indirection.
Re: Moose stringification overloading isn't working
by tobyink (Canon) on Feb 10, 2013 at 08:54 UTC

    You're not using something like namespace::autoclean are you? It breaks overloading. Try namespace::sweep instead.

    package Cow { use Moo; has name => (is => 'lazy', default => sub { 'Mooington' }) } say Cow->new->name
Re: Moose stringification overloading isn't working
by Anonymous Monk on Feb 09, 2013 at 23:48 UTC
      Drat. Does that mean the concept and execution seems sound and you need more detail, or just that you didn't look at it because it wasn't a self-contained bagged sample?

      As I said, the small sample I built worked, so I'd have to chase it up the tree. Which I will if necessary, if there's nothing obviously wrong with the approach.

        It means code is clearer than words :) and your question is unclear (to me)

        If I had the same question, first thing I would do is try to replicate it in a short self contained example, and then I'd either have a test case, or I'd figure out where I'm confused, or have some code to show what I'm trying to accomplish

        Code can be much clearer than English

Re: Moose stringification overloading isn't working
by Anonymous Monk on Feb 10, 2013 at 07:29 UTC

    Your output has two different classes in it:

    Zep is              OT::Zeppelin::AddVendorKey 
    stringifies as      OT::Zeppelin::AddVendorKey….
    _stringify returns  OT::DB::Result::Upload...

    So it looks like the line $this->row->ID can return two different objects.

    The 'use overload' docs say:

    The subroutines for '""' , '0+' , and 'bool' can return any arbitrary Perl *value*. If the corresponding operation for this *value* is overloaded too, the operation will be called again with this *value*.
    As a special case if the overload returns the object itself then it will be used directly. An overloaded conversion returning the object is probably a bug, because you're likely to get something that looks like YourPackage=HASH(0x8172b34) .

    Based on the order of the output, I would say that $this->row->ID is returning $this in some cases, and in other cases it is returning an object of the class OT::DB::Result::Upload, and that class has also overloaded '""'.

    Here is a simple example of that:

    use strict; use warnings; use 5.012; ############## { package Point; use Moose; # automatically turns on strict and warnings has 'x' => (is => 'rw', isa => 'Int'); has 'y' => (is => 'rw', isa => 'Int'); use overload '""' => \&_stringify; sub _stringify { state $count; my ($rhs, $_lhs, $swap) = @_; $count++; if ($count < 2) { return $rhs; } else { return D->new; } } } ################ { package Point3D; use Moose; extends 'Point'; has 'z' => (is => 'rw', isa => 'Int'); } ############### { package D; use Moose; use overload '""' => sub { my $class = ref shift; return "$class|hello" }; } ############### my $p3d = Point3D->new(x=>10, y=>20); say "$p3d"; say $p3d->_stringify; --output:-- Point3D=HASH(0x100bc5078) D|hello
      What happens if you use double quotes twice? And what happens if you call _stringify() twice? Any difference?