Beefy Boxes and Bandwidth Generously Provided by pair Networks
go ahead... be a heretic
 
PerlMonks  

See if a certain package has a certain sub, without executing that sub

by muba (Priest)
on Mar 20, 2004 at 15:03 UTC ( #338296=perlquestion: print w/ replies, xml ) Need Help??
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 :)

Comment on See if a certain package has a certain sub, without executing that sub
Select or Download Code
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!

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://338296]
Approved by gmax
Front-paged by cchampion
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others meditating upon the Monastery: (9)
As of 2015-07-06 06:04 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    The top three priorities of my open tasks are (in descending order of likelihood to be worked on) ...









    Results (70 votes), past polls