10

I have a class where I want to apply string overloading on its id attribute. However, Moose doesn't allow string overloading on attribute accessors. For example:

package Foo;
use Moose;
use overload '""' => \&id, fallback => 1;
has 'id' => (
    is => 'ro',
    isa => 'Int',
    default => 5,
);

package main;
my $foo = Foo->new;
print "$foo\n";

The above will give an error:

You are overwriting a locally defined method (id) with an accessor at C:/perl/site/lib/Moose/Meta/Attribute.pm line 927

I have tried a couple of options to get around this:

  1. Marking id is => bare, and replacing it with my own accessor: sub id {$_[0]->{id}}. But this is just a hack.

  2. Having the string overloader use another method which just delegates back to id: sub to_string {$_[0]->id}.

I'm just wondering if anyone has a better way of doing this?

stevenl
  • 6,736
  • 26
  • 33

2 Answers2

7
use overload '""' => sub {shift->id}, fallback => 1;

Works fine for me.

Hynek -Pichi- Vychodil
  • 26,174
  • 5
  • 52
  • 73
  • Which is essentially option 2 from the question in shorter syntax. I'm not saying it's bad but it would still be interesting to know why the first approach from the question fails. – musiKk Aug 29 '11 at 15:28
  • The shorter syntax is slightly cleaner. With the 3 arg issue, I guess this has to be the way to go. – stevenl Aug 30 '11 at 04:16
5

I believe you are getting an error because \&id creates a placeholder for a sub to be defined later, because Perl will need to know the address that sub will have when it is defined to create a reference to it. Moose has it's own checks to try to avoid overwriting methods you define and reports this to you.

Since I think what you really want to do is call the id method when the object is used as a sting like so:

use overload '""' => 'id', fallback => 1;

From the overload documentation

Values specified as strings are interpreted as method names.

Ven'Tatsu
  • 3,565
  • 16
  • 18
  • It doesn't work. I'm still getting error message: `Cannot assign a value to a read-only accessor at reader Foo::id (defined at - line 4) line 3 Foo::id('Foo=HASH(0x12ffa10)', undef, '') called at - line 12` – Hynek -Pichi- Vychodil Aug 29 '11 at 20:14
  • @Hynek, it looks like `overload` is passing parameters to the method, which Moose interprets as an attempt to set the attribute. So you'll need to use an intermediary sub, as you did in your answer. – cjm Aug 29 '11 at 20:35
  • 4
    I see that this error is because `overload` always passes 3 args to the method from [Overload - calling conventions](https://metacpan.org/module/overload#Calling-Conventions-and-Magic-Autogeneration) – stevenl Aug 30 '11 at 03:46