$ perl package_cache.pl
Can't 1
Can 2
I'm a Foo
Can 3
Undefined subroutine &Foo::foo called at package_cache.pl line 38.
$ cat package_cache.pl
#!/usr/bin/perl -w
use strict;
package Foo;
sub new {
bless [];
}
package main;
my $code = <<'EOP';
package Foo;
sub foo {
my $self = shift;
print "I'm a $self\n";
}
1;
EOP
my $f = Foo->new;
print Foo->can('foo') ? "Can 1\n" : "Can't 1\n";
eval $code or die $@;
print Foo->can('foo') ? "Can 2\n" : "Can't 2\n";
Foo->foo();
undef &Foo::foo;
print Foo->can('foo') ? "Can 3\n" : "Can't 3\n";
Foo->foo();
__END__
(I'm writing Storable regression tests)
Nicholas Clark
Probably, as it's cleared in other places.
So I tried this :
NOT TO BE APPLIED
--- pp.c (revision 3350)
+++ pp.c (working copy)
@@ -797,6 +797,7 @@ PP(pp_undef)
GV* gv = CvGV((CV*)sv);
cv_undef((CV*)sv);
CvGV((CV*)sv) = gv;
+ GvCVGEN(gv) = PL_sub_generation++;
}
break;
case SVt_PVGV:
This solves your problem but this makes t/op/method.t and t/op/exists_sub.t
unhappy.
As a workaround you can undef the glob or delete the stash entry (instead of
undeffing the sub.)
I changed my mind.
When you C<undef> a sub, it still C<exists>. So perl is correct here. NOTABUG.
But what happens when you call it?
Arthur
Obviously, a fatal error. (This is all because Perl makes a distinction
between subs that are defined -- they have a CV -- and the ones that
only exist -- they only have a symbol table entry, as when you write a
forward declaration.)
Fails to find a sub body, tries AUTOLOAD.
The behaviour is consistent with stubbing a sub:
perl -lwe 'sub C {print main->can("foo") ? "Can" : "Can'\''t"}; &C; eval "sub foo; 1" or die $@; &C; &foo;'
Can't
Can
Undefined subroutine &main::foo called at -e line 1.
It's consistent. Not everyone finds it helpful.
Nicholas Clark
I think so.
If I recall correctly cache is re-built if 'subgeneration' doesn't match.
>ie, is "Can 3" in the
>following an error?
I think so.
I think that all that is needed for cache flush is the
PL_sub_generation++
I don't think you need to mess with the GV.
I agree with that now.
>>
>
>But what happens when you call it?
Same as what happens if you predeclare it
sub foo;
But never get round to defining it. Try for AUTOLOAD or give message
Nick C was seeing.
>
>Arthur
For some reason that I've not tried to understand, in Nicholas' test
case, the GvCVGEN was == 0, making the CV effectively un-un-cacheable.
In which case can() is a horribly misleading name. Besides telling you that it
can() not, even though it really can when AUTOLOAD is involved. The following
code (posted earlier in the 'undeffing CV' thread) demonstrates that it's
totally unreliable, since while the function "exists" it has no CV, and
therefore it can not be used, while can() says that it is.
#/tmp/can
use warnings;
sub foo { };
*main::foo = sub { };
undef &main::foo;
my $cv = main->can('foo');
$cv->() if $cv;
% perl /tmp/can
Subroutine main::foo redefined at /tmp/can line 3.
Not a CODE reference at /tmp/can line 6.
Notice that my example's error is different and much more unclear to the end
user than Nick's example that started this thread.
I'd suggest to deprecate can() completely, because it's not reliable. Instead
replace it with has() which just checks the entry, and has_cv() that is really
callable.
__________________________________________________________________
Stas Bekman JAm_pH ------> Just Another mod_perl Hacker
http://stason.org/ mod_perl Guide ---> http://perl.apache.org
mailto:st...@stason.org http://use.perl.org http://apacheweek.com
http://modperlbook.org http://apache.org http://ticketmaster.com
You're obviously confusing can() with will(). :-)
--
Chip Salzenberg - a.k.a. - <ch...@pobox.com>
"I wanted to play hopscotch with the impenetrable mystery of existence,
but he stepped in a wormhole and had to go in early." // MST3K
I disagree. can() returning a CODE ref for subs that have only a forward
declaration is a feature, as explained in the UNIVERSAL manpage, which
precisely documents the current behaviour.
You can test the definedness of a method with :
sub f; $f=main->can("f"); print defined &$f
So what's the meaning of can() if it can't? it should be declared() or
exists() then.
And wantarray should be wantlist and local should be temp, yeah, yeah.
I fail to see how your sarcasm applies, Chip. What prevents us from adding new
methods that really do what they seem to be saying they are doing?
This seems to be a common misconception. C<undef &foo> does *not* delete
the CV; the CV still exists, but its pad and optree have been thrown away,
and any attempt to execute it gives an error.
It's comparable with C<$foo ="abc"; undef $foo>: $foo still exists as a
PV, but its SvPVX is null, and any attempt to use it gives an error (well,
a warning anyway).
$ perl583 -MDevel::Peek -e 'sub f{}; undef &f; Dump(\&f)'
SV = RV(0x818d048) at 0x8185458
REFCNT = 1
FLAGS = (TEMP,ROK)
RV = 0x818544c
SV = PVCV(0x8180f40) at 0x818544c
REFCNT = 2
FLAGS = ()
IV = 0
NV = 0
COMP_STASH = 0x8175a28 "main"
START = 0x8185b50 ===> 14385
ROOT = 0x0
XSUB = 0x0
XSUBANY = 0
GVGV::GV = 0x81854c4 "main" :: "f"
FILE = "-e"
DEPTH = 0
FLAGS = 0x0
OUTSIDE_SEQ = 91
PADLIST = 0x0
OUTSIDE = 0x8175c68 (MAIN)
--
Standards (n). Battle insignia or tribal totems.
AUTOLOAD is meant to be transparent.
From the AutoLoader docs:
Subroutine Stubs
In order for object method lookup and/or prototype checking to operate
correctly even when methods have not yet been defined it is necessary
to "forward declare" each subroutine (as in sub NAME;). See the
section on SYNOPSIS in the perlsub manpage. Such forward declaration
creates "subroutine stubs", which are place holders with no code.
I want $foo->can("bark") to be true even if the back() method hasn't been loaded yet.
Tim.
Why, nothing prevents us, of course. But just because something can()
be done doesn't mean it will(), or should().
First, I see no particular benefit to Perl in creating what is
basically an additional alias for a facility that, for reasons of
backward compatibility, needs to remain in place forever anyway.
It's not a renovation if you leave the old construction in place.
Second, for most cases, can() actually does return the right answers.
Do you think that functional stubs just appear out of nowhere? Of
course not. In point of fact, function stubs almost always serve as
markers for functions that *will* be AUTOLOADed on demand, so the
boolean true answer from can() is entirely correct.
I observe that you're trying to make subroutines go away entirely
after the're already defined. Well, that's just dandy, but it's not
what C<undef &func> does, and for reasons of backward compatibility,
it never will be. If you feel like you must invent something, why not
invent Death, Destroyer of Subroutines? That would be new *and* useful.
Candidate:
C:\>perl -e "sub foo {} delete &foo"
delete argument is not a HASH or ARRAY element or slice at -e line 1.
This also fits nicely with the existing meaning of undef vs. delete.
--
Brent "Dax" Royal-Gordon <br...@brentdax.com>
Perl and Parrot hacker
Oceania has always been at war with Eastasia.
But my point is that it's *not* bogus in the presence of AUTOLOAD:
package StasExampleClass;
sub bar; # stub so can() returns true
sub AUTOLOAD {
if (substr($AUTOLOAD, rindex($AUTOLOAD, ':')+1) eq 'bar') {
*bar = sub { something_interesting };
goto &bar;
}
}
(BTW, I just realized that the substr/rindex hack above avoids a
regex, which would reset $1 etc, and would therefore interfere with
passing $1 as a parameter. >>bag_o_tricks)
> > If you feel like you must invent something, why not
> > invent Death, Destroyer of Subroutines? That would be new *and* useful.
>
> Unfortunately I don't understand enough internals to write one. Do you?
Is this a trick question? :-)
I like that explanation. My guess is that many others use can() to populate a
ref to a sub:
my $cv = foo->can('bar');
$cv->(@args) if $cv;
So may be the manpage should mention that the above code is bogus and suggest
the right way to write it?
> First, I see no particular benefit to Perl in creating what is
> basically an additional alias for a facility that, for reasons of
> backward compatibility, needs to remain in place forever anyway.
> It's not a renovation if you leave the old construction in place.
>
> Second, for most cases, can() actually does return the right answers.
> Do you think that functional stubs just appear out of nowhere? Of
> course not. In point of fact, function stubs almost always serve as
> markers for functions that *will* be AUTOLOADed on demand, so the
> boolean true answer from can() is entirely correct.
Agreed.
> I observe that you're trying to make subroutines go away entirely
> after the're already defined. Well, that's just dandy, but it's not
> what C<undef &func> does, and for reasons of backward compatibility,
> it never will be. If you feel like you must invent something, why not
> invent Death, Destroyer of Subroutines? That would be new *and* useful.
Unfortunately I don't understand enough internals to write one. Do you?
__________________________________________________________________
And exists accepts a &foo argument. So that's consistent here as well.
(Currently you delete $::{'foo'} to kill the subroutine.)
Yes, I tried that a couple weeks ago and was surprised it didn't work.
>>TODO
One of my pet peeves is code demanding predictions of the future.
"Will I be able to open the file? Will I be able to call the method?
And what about Naomi? Perspiring minds want to know!"
The right approach is, of course: *Try* it, and see if it works. In
the case of a file, just *open* it and check the return value and $!.
In the case of a method, if you're not sure whether the method is
really there, just *call* it in an eval block and check the return
value and $@.
my $ret = eval { $obj->foo };
if ($@ =~ /^Can't locate \w+ method "foo"/) {
# well, I guess it's not there
But how do you know if there is AUTOLOAD *and* that it'll handle that
particular sub.
I guess, i shouldn't have called it "bogus", but "not necessarily work" or
"not necessarily DWIM".
>>>If you feel like you must invent something, why not
>>>invent Death, Destroyer of Subroutines? That would be new *and* useful.
>>
>>Unfortunately I don't understand enough internals to write one. Do you?
>
>
> Is this a trick question? :-)
Sort of. If you know how to write a Death, Destroyer of Subroutines, that
would be great if you could write it.
> But how do you know if there is AUTOLOAD *and* that it'll handle that
> particular sub.
If the coder were reasonably competent, predeclaring the subroutine
should be a good guide.
I've always understood can() and declarations to make this sort of thing
possible:
#! perl -w
use strict;
use vars '$AUTOLOAD';
use Test::More tests => 2;
sub foo;
sub AUTOLOAD
{
if (substr($AUTOLOAD, rindex($AUTOLOAD, ':')+1)
eq 'foo')
{
*foo = sub { 'called foo' };
goto &foo;
}
}
can_ok( 'main', 'foo' );
my $foo = main->can( 'foo' );
is( $foo->(), 'called foo',
'can() should return subref populatable by AUTOLOAD' );
-- c
You're missing the point. DO NOT ASK whether the function will work.
That question has no answer. Behold UNIVERSAL::AUTOLOAD and despair.
Instead, arrange your code to simply call the function *when* it is
needed (not before). If, when you call it, it turns out not to be
there, *then* you can note the error and/or try some error recovery.
Hmmm...
sub foo { system 'something evil' }
I don't think trying to execute a sub is the right way to find out
whether it exists...
Liz
That intent was not clear to me from your message. It is now.
Liz
It is. Quoting 'perldoc UNIVERSAL':
"can" cannot know whether an object will be able to provide a method
through AUTOLOAD, so a return value of undef does not necessarily mean
the object will not be able to handle the method call.
It goes on to explain the stub technique, which is, however, beside
the point of your question:
To get around this some module authors use a forward declaration (see
perlsub) for methods they will handle via AUTOLOAD. For such 'dummy'
subs, "can" will still return a code reference, which, when called,
will fall through to the AUTOLOAD.
Shouldn't this be documented?
Yves
Should delete *foo{TYPE} in general work? I'd really hate to add to the
places where &foo means "the sub named foo" and not "call foo, ignoring
prototypes and not creating a fresh @_". (OTOH, the existing variants
of delete are $foo{bar}, not \$foo{bar}.)
-=- James Mastros
(Hoping he's not in over his head again.)
That wording ought to be stronger. Without stubs inheritance won't
do the right thing. The AutoLoader docs say it better:
Subroutine Stubs
In order for object method lookup and/or prototype checking to operate
correctly even when methods have not yet been defined it is necessary
to "forward declare" each subroutine (as in "sub NAME;"). See "SYNOP-
SIS" in perlsub. Such forward declaration creates "subroutine stubs",
which are place holders with no code.
Tim.