Re: Yet another does-function-exist question (eval sub)
by tye (Sage) on Apr 14, 2007 at 16:22 UTC
|
sub definedWord
{
my( $word )= @_;
return eval "use strict; my \$x= sub { $word }; 1"
|| ( warn("$@\n"), $@ !~ /^Bareword/ );
}
@ARGV= qw( definedWord time system foo BEGIN if -e lt goto last )
if ! @ARGV;
for( @ARGV ) {
printf "$_:\t%sdefined\n", definedWord($_) ? "" : "UN";
}
is one interesting interpretation, producing:
definedWord: defined
time: defined
system: defined
Bareword "foo" not allowed while "strict subs" in use at (eval 4) line
+ 1.
foo: UNdefined
BEGIN: defined
syntax error at (eval 6) line 1, at EOF
if: defined
-e: defined
syntax error at (eval 8) line 1, near "{ lt"
lt: defined
goto: defined
last: defined
| [reply] [d/l] [select] |
|
@ARGV= qw( ; "foo" 123 {} [] ) if ! @ARGV;
# etc.
__END__
;: defined
"foo": defined
123: defined
{}: defined
[]: defined
| [reply] [d/l] |
|
| [reply] |
|
If that really matters for an example, definedWord could be just powered with regex. ++tye.
Open source softwares? Share and enjoy. Make profit from them if you can. Yet, share and enjoy!
| [reply] |
|
| [reply] |
Re: Yet another does-function-exist question
by Joost (Canon) on Apr 14, 2007 at 15:56 UTC
|
my $is_function = $package->can($function_name);
note that that does not work for build-ins.
| [reply] [d/l] |
Re: Yet another does-function-exist question
by kyle (Abbot) on Apr 14, 2007 at 16:29 UTC
|
use List::Util qw(min);
sub foo {}
$x = time();
foreach my $thing ( qw( x foo min time ) ) {
printf "$thing is code: %s\n",
( ref *{$main::{$thing}}{CODE} ) ? 'Yes' : 'No';
}
__END__
x is code: No
foo is code: Yes
min is code: Yes
time is code: No
Perhaps you could tell us what problem you're really trying to solve?
If you have some string, and you want to know if it could do something under eval without actually executing it, perhaps you could use 'perl -c' for that. Or, to be really ugly, shell out and see what 'perldoc -f' has to say about it (being very careful about quoting the argument, of course). That would detect built-ins, and you could use one of the other methods listed here for detecting everything else. | [reply] [d/l] [select] |
|
| [reply] |
Re: Yet another does-function-exist question
by f00li5h (Chaplain) on Apr 14, 2007 at 15:32 UTC
|
sub bar { print 'woot' }
for my $thing (qw/ foo bar /){
print "$thing :$/";
eval{
no strict refs;
&{$thing}(@_); # possibly a nasty symbolic reference
};
warn "You can not call $thing: $@ " if $@;
}
gives you something like:
The main point being, that you can just catch the die from eval and move on.
Why ask if something looks like it will fail, when you can just suck it and see?
if you're involving objects, UNIVERSAL's can may also interest you
@_=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;
| [reply] [d/l] [select] |
|
$func = "format_hard_drive";
print "Good news, function exists!" if eval { &$func() };
| [reply] [d/l] |
|
You can do it one of two ways.
- Check that the thing is valid before hand (as ref $coderef in my class below does)
- 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)
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)
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;
| [reply] [d/l] [select] |
|
|