Beefy Boxes and Bandwidth Generously Provided by pair Networks
Do you know where your variables are?

Generating similar functions in unrelated objects

by t'mo (Pilgrim)
on Aug 31, 2001 at 02:03 UTC ( #109219=note: print w/replies, xml ) Need Help??

in reply to Re (tilly) 1: Why I hate File::Find and how I (hope I) fixed it
in thread Why I hate File::Find and how I (hope I) fixed it

Suppose you wanted to do something like this to a family of related objects. How would you assign the anonymous function to be a method of each class? (I can do that trick in JavaScript using ObjectName.prototpye.methodName, but how would I do that in Perl?)

For example, what I would like to do is:

... sub ObjectToString { my $name = shift; return sub { my $s = $name . $self->getParametersAndValues(); return $s; } } ... package Fu; sub toString = ObjectToString("Fu"); ... package Bar; sub toString = ObjectToString("Bar"); ... package Baz; sub toString = ObjectToString("Baz"); ...

Then I would use it like this:

my ($foo, $bar, $baz); $foo = Fu->new(); # do stuff with foo... print $foo->toString(); $bar = Bar->new(); # do stuff with bar... print $bar->toString(); ...

The obvious answer here is to use Inheritance™, but what if, for some reason, I don't want to use inheritance? Can I still accomplish what I want to?

Replies are listed 'Best First'.
Re (tilly) 3: Generating similar functions in unrelated objects
by tilly (Archbishop) on Aug 31, 2001 at 07:25 UTC
    You would want to do a typeglob assignment. If you assign an anonymous function to a typeglob, you define that function. Like this:
    package Stringify; sub objectToString { my $name = shift; return sub { $name . (shift)->getParametersAndValues(); }; } # Time passes package Fu; *toString = Stringify::objectToString("Fu");
    But I should note that you can make this nicer with overload and an autogenerated method. For instance:
    package Stringify; use strict; use Carp; sub import { my $pkg = caller(); my $code = qq( # A trick for custom error reporting - see perlsyn. \n# line 1 "'Autogenerated for $pkg by Stringify'" package $pkg; use overload '""' => sub { __PACKAGE__ . (shift)->getParametersAndValues(); }; ); eval($code); if ($@) { confess("Cannot autogenerate stringification for package '$pkg': $ +@ The code is:\n$code"); } } 1;
    would allow you to simply:
    package Fu; use Stringify; # Use objects as strings, and they stringify
    If you want you could create an autogenerated function called toString and pass a reference to that function to overload.

      You know what happened, don't you? Just as I was leaving the building, not more than five minutes after I asked the question, the answer came to me: symbol table. :-)

      The import approach is interesting. It gives me more food for thought, especially in relation to this question I asked about writing your own import. Thanks.

        Are custom imports a good idea?

        Can I say it depends?

        Most of what I was saying about AUTOLOAD at Re (tilly) 4: Perl and Objects, how do you resolve the two? applies to custom imports as well. A custom import is like a very good sword without a hilt. It can cut really well, but you need to be very cautious before using it.

        My rule of thumb is this. If my custom import could be done with Exporter, I don't use it. If it makes for a significantly improved interface and works very differently, then I will consider it. But if I won't actually use it unless I am going to make it a meme in the body of code that I am working on. It doesn't matter how nice each customized rule is, a million and one customized high-level interfaces is unmaintainable.

        Or, to put it a different way, It is OK to be clever, but only one person should be being clever at a time.

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: note [id://109219]
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others browsing the Monastery: (8)
As of 2017-10-18 16:56 GMT
Find Nodes?
    Voting Booth?
    My fridge is mostly full of:

    Results (249 votes). Check out past polls.