http://qs1969.pair.com?node_id=338296

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

Hi,

I am writing a simple plugin system. I'm not sure whether I'm going to use it, but it's more like a way to explore Perl.

So, I have an array which contains packages names. Those packages should have a sub 'ReceiveMessage'.
A package called Communications contains a sub 'SendMessage'.
This SendMessage loops over the array to check which packages do have a ReceiveMessage and send a message to it. Currently, the array consists of one item: "Communications".

package Communications; sub SendMessage { my $msg = join("", @_); foreach my $cpack (@main::plugpack) { if (defined eval "${cpack}::ReceiveMessage") { eval "\&${cpack}::ReceiveMessage('$msg')"; } } } sub ReceiveMessage { print "Communications::ReceiveMessage('$_[0]')\n"; }
Of course I call the SendMessage sub once: &Communications::SendMessage("Hello, World!");
The strange thing is, I get output like I called SendMessage twice:
Use of uninitialized value in concatenation (.) or string at D:\device +\modem\internet\Xitami\cgi-bin\index.pl line 48. Communications::ReceiveMessage('') Communications::ReceiveMessage('Hello, World!')
It appears to me that ReceiveMessage is not only called when the message is sent, but also when SendMessage checks it's existance. How can I prevent this?

Update: just clarified the last paragraph a little
Update: removed line of code which was coded in a inconsistent style and only was there for debug purposes :)

Replies are listed 'Best First'.
Re: See if a certain package has a certain sub, without executing that sub
by gmax (Abbot) on Mar 20, 2004 at 15:27 UTC

    Use the can method (it's a method of the UNIVERSAL package, so every class in Perl has access to it).

    #!/usr/bin/perl use strict; use warnings; package Communications; sub SendMessage { my $packages = shift; my $msg = shift; for (@$packages) { if ($_->can('ReceiveMessage') ) { $_->ReceiveMessage($msg); } else { print "$_ can't ReceiveMessage\n" } } } sub ReceiveMessage { print __PACKAGE__, "::ReceiveMessage('$_[1]')\n"; } package Second; sub ReceiveMessage { print __PACKAGE__, "::ReceiveMessage('$_[1]')\n"; } package Other; sub nothing { print "\n"; } package main; my @packages = qw(Communications Other Second); Communications::SendMessage( \@packages, 'hello'); __END__ output: Communications::ReceiveMessage('hello') Other can't ReceiveMessage Second::ReceiveMessage('hello')
     _  _ _  _  
    (_|| | |(_|><
     _|   
    
      Wow! This one is great! It's also nice to read:
      "if it can receive message" :)
      Thank you a lot!