Beefy Boxes and Bandwidth Generously Provided by pair Networks
Problems? Is your data what you think it is?

comment on

( #3333=superdoc: print w/replies, xml ) Need Help??

You can do it one of two ways.

  1. Check that the thing is valid before hand (as ref $coderef in my class below does)
  2. Check when you call that the result is valid (as the trigger_event sub will do if you remove the test in the first point)

At the risk of getting a TL;DR, here's something that takes coderefs and then dispatches events with them, as I wrote this, I realised that it's surprisingly long for a simple example ;)

This is the class that takes care of dispatching the events (to a single handler for each event type)

package f00li5h::Events; use Class::Std; { use strict; my %callbacks :ATTR(); =head1 register_callback $object->register_callback( event_name => $subref ); the subref will be passed a list of args provided when the event is tr +iggered, and will be protected in an eval block. =cut sub register_callback { my($self, $name, $subref) = @_; unless ( ref $subref eq 'CODE' ) { use Data::Dumper; warn "You call that a callback? it's not a real coderef, s +o i'm going to ignore it! :" . Dumper( $subref ); return; } $callbacks{ ident $self }->{ $name } = $subref; } =head1 trigger_event trigger an event, will return the exception or the result of the sub $object->trigger_event( event_name => $argref); $object->trigger_event( event_name => [ $user, $data, $foos ...] ); =cut sub trigger_event { my($self, $name, @data) = @_; warn "Callback '$name' not registered" if not defined $callbacks{ ident $self }-> { $name }; my $result; eval { $result = $callbacks{ ident $self }->{ $name }->( @data ); }; return $@ if $@; # if calling the handler fails, return the e +xception return $result; # toherwise return what the sub returned } }

This is the client code, that registeres event handlers (to be used as callbacks) and triggers the actual events on the object. Normally, the object would find it's own events, and handle them within a run() type method (Tl's MainLoop for example)

package main; use strict; { # these are the events to be triggered my @events= ( [moose => q/Moose saves thousands from terror attack!/] , [antelope => q/Antelope wins baseball game /], [moose => q/Moose alerts medial over email scams!/] , ); sub events_happening { # this sub will just iterate over @events, using closure funky +ness # it will return an empty list when there are none left ( henc +e the [] ) @{ shift @events || [] }; } } # here are some callbacks sub moose { print "[HANDLED moosed ->", @_ , " for you ]\n"; } sub antelope { print "[ANTELOPE HANDLER WON'T BE CALLED->", @_ , "]\n" +; } # set up our event handling object my $handler = f00li5h::Events->new(); # we pass in a proper coderef here $handler->register_callback( 'moose' => \&moose ); # here, we just pass in a name, the class will reject it... $handler->register_callback( 'antelope' => 'antelope' ); # this one uses an anonymous sub (which is a coderef) # it would run happily, if i had a 'llama' event in the list # you can add that as an exercise if you want ;) $handler->register_callback( 'llama' => sub { print "I'm there is no event to trigger me, because f +00li5h thought of adding me after he'd written and run the code"; } ); use Data::Dumper; # neat, an event loop, normally, you would $f00li5h->run() and have th +e object get it's events from somewhere while( my($event_name, @event_args) = events_happening ){ my $result = $handler->trigger_event($event_name, @event_args); warn "Triggering $event_name with (" . join( ",", @event_args ) . ") resulted in ". Dumper($result) if $result; }

You call that a callback? it's not a real coderef, so i'm going to ign +ore it! :$VAR1 = 'antelope'; [HANDLED moosed ->Moose saves thousands from terror attack! for you ] Triggering moose with (Moose saves thousands from terror attack!) resu +lted in $VAR1 = 1; Callback 'antelope' not registered at callback line 29. Triggering antelope with (Antelope wins baseball game ) resulted in $V +AR1 = 'Can\'t use string ("") as a subroutine ref while "strict refs" + in use at callback line 33. '; [HANDLED moosed ->Moose alerts medial over email scams! for you ] Triggering moose with (Moose alerts medial over email scams!) resulted + in $VAR1 = 1;

The class will reject 'antelope' because it's not a real coderef, although if you were to pass in 'main::antelope' as the name, and remove the check for ref $coderef, you should be able to use just names of subs. I don't see why you would want to do this, since it's the same number of characters to write \& as it is to enclose the sub's name quote likes

Justification: this does answer your question about checking if it's callable before hand (because it uses ref $subref to decide if it can be callled (long before the events actually turn up). This is a fairly painless way to check if something is callable, you can also use anonymous subs if you want

Hope this helps.

@_=qw; ask f00li5h to appear and remain for a moment of pretend better than a lifetime;;s;;@_[map hex,split'',B204316D8C2A4516DE];;y/05/os/&print;

In reply to Re^3: Yet another does-function-exist question by f00li5h
in thread Yet another does-function-exist question by xaprb

Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post; it's "PerlMonks-approved HTML":

  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.
  • Log In?

    What's my password?
    Create A New User
    and the web crawler heard nothing...

    How do I use this? | Other CB clients
    Other Users?
    Others romping around the Monastery: (4)
    As of 2021-01-16 11:53 GMT
    Find Nodes?
      Voting Booth?