Devanchya has asked for the wisdom of the Perl Monks concerning the following question:

I'm currently switching some code into a more Object Oriented style. I'm not pretending it's good Object Oriented code. It's old code that I'm puting into objects in order to manage better.

I have everything working, except the code use to use hash code references as way to dynamically add in new function to the program by dropping module files into a directory. It worked, and the ability is loved...

It worked like this: $dispatch{status_form} = \&status_form;

Now the problem is, when the module is built objects in mind it becomes $self->status_form etc. Is there a way to retain the old code refence with a object hash like this?

The code reference was later accessed by doing $dispatch{status_form}->();

If I'm out to lunch, feel free to tell me that as well.
--
Even smart people are dumb in most things...
  • Comment on Old Code reference wants new life as Object.

Replies are listed 'Best First'.
Re: Old Code reference wants new life as Object.
by ikegami (Patriarch) on Dec 08, 2006 at 04:55 UTC

    Build a small wrapper function.

    my $self = ...; $dispatch{status_form} = sub { $self->status_form(@_) };

    If I'm out to lunch, feel free to tell me that as well.

    Not at all. Callbacks are frequently done this way in Perl.

      Thanks this works perfectly.

      I was orignally attempting to do this with just { } thinking a anon-sub would work. Guess I forgot to run the sub.
      --

      Even smart people are dumb in most things...

        { ... } creates an anonymous hash.
        sub { ... } creates an anonymous sub. It doesn't execute the sub.

Re: Old Code reference wants new life as Object.
by revdiablo (Prior) on Dec 08, 2006 at 17:26 UTC

    Your question sounds somewhat interesting, but -- as the previous two replies indicate -- it is a bit vague. After reading it I am left with a few questions.

    Do you want to:

    • Remove the dispatch table altogether, and replace it with something more "objecty"?
    • Leave the dispatch table there but access it through an object method call?

    And do you need help:

    • Updating the calling code?
    • Updating the plugin code?

    As you can see, there are many different directions this could go. Maybe one of the previous responses answered the question for you, but maybe not. Perhaps if you could clarify your question, we could be more certain.

      Thanks for the responces... I am trying to maintain the depatch table at this time, as it is integrated into the main program preety heavly. If there is a better way to do it with out loosing the dynamic option, then that most likely would work. I considered using inheritance etc but it didn't work right for the option.

      Right now each of the existing plugin's have a load section which loads a code reference into a global dispatch hash:
      $dispatch{login} = \&login;
      $dispatch{slogin} = \&secure_login;
      The script then uses a value of a specific varible to determin what to do.
      $dispatch{default} = \&show_option_menu; #if nothing else we will show the menu

      $dispatch->{$dothis_now}->() # does the code ref.

      Now as you can tell, doing a code ref with \&login for example will work. It will not run the code when loaded into the hash, and waits nicely until it is wanted.

      $dispatch{self_test} = $self->login;

      Will execute the code before it is placed in the hash.

      I have not yet tested the other options given, but will as soon as I'm next to my development machine. But hopefully this clears it up a bit.

      It may be both the calling and the plugin code need to be 'fixed' to work properly.

      --

      Even smart people are dumb in most things...

        In that case, the easiest thing to do is probably:

        $dispatch{self_test} = sub { $self->login };

        This will create an anonymous code reference that makes a closure on $self, so everything should be in place when the code actually gets called.

        Update: Er, which is exactly what ikegami responded with. I guess I should have re-read the original replies before posting.

Re: Old Code reference wants new life as Object.
by jdporter (Paladin) on Dec 08, 2006 at 16:21 UTC

    It sounds to me like you're saying you want to be able to call $obj->status_form without defining it, and have it execute the code refs stored in the dispatch table. If so, then I think ikegami is mistaken; instead, you could use AUTOLOAD for this purpose:

    { package Foo; our $AUTOLOAD; use Carp; sub AUTOLOAD { my $self = shift; my($meth) = $AUTOLOAD =~ /.*::(.*)/; return $dispatch{$meth}->($self) if ref $dispatch{$meth}; Carp::cluck( "unknown $meth\n" ); } sub DESTROY { } # to keep this one from calling AUTOLOAD }
    We're building the house of the future together.