defined(&func) and Exporter

P

Peter Michael

Hi,

can anyone please explain to me why subroutines resulting
from constants imported with Exporter are not considered
to be defined?

perl -MFcntl -le 'print &F_SETLK'

shows that a subroutine F_SETLK can be called. But

perl -MFcntl -le 'print "defined" if defined &F_SETLK'

shows that it is not considered to be defined.

The consequence is that a constant imported this way can
accidentely be overridden by a 'require "fcntl.ph"'. The
..ph contains (on Linux)

eval 'sub F_SETLK () {6;}' unless defined(&F_SETLK);

but &F_SETLK is not considered to be defined after the use()age
of Fcntl and is thus overridden.

Thanks for any explanations.

Peter
 
R

Rafael Garcia-Suarez

Peter said:
Hi,

can anyone please explain to me why subroutines resulting
from constants imported with Exporter are not considered
to be defined?

perl -MFcntl -le 'print &F_SETLK'

shows that a subroutine F_SETLK can be called. But

perl -MFcntl -le 'print "defined" if defined &F_SETLK'

shows that it is not considered to be defined.

Because you haven't called it : Fcntl constants are autoloaded.
However, it exists.
 
C

Charles DeRykus

Hi,

can anyone please explain to me why subroutines resulting
from constants imported with Exporter are not considered
to be defined?

perl -MFcntl -le 'print &F_SETLK'

shows that a subroutine F_SETLK can be called. But

perl -MFcntl -le 'print "defined" if defined &F_SETLK'

shows that it is not considered to be defined.

The consequence is that a constant imported this way can
accidentely be overridden by a 'require "fcntl.ph"'. The
.ph contains (on Linux)

eval 'sub F_SETLK () {6;}' unless defined(&F_SETLK);

but &F_SETLK is not considered to be defined after the use()age
of Fcntl and is thus overridden.

I believe the problem is that the sub gets autoloaded
the first time it's seen. Your code is testing whether
it's defined before the autoloading has occurred.

From 'perldoc -f defined':

Note that a subroutine which is not defined may still
be callable: its package may have an "AUTOLOAD" method
that makes it spring into existence the first time that
it is called -- see the perlsub manpage.


hth,
 
P

Peter Michael

Hi Charles,

Charles DeRykus said:
I believe the problem is that the sub gets autoloaded
the first time it's seen. Your code is testing whether
it's defined before the autoloading has occurred.

From 'perldoc -f defined':

Note that a subroutine which is not defined may still
be callable: its package may have an "AUTOLOAD" method
that makes it spring into existence the first time that
it is called -- see the perlsub manpage.

ok; thanks for the hint.
So I am going to call the sub first to get the constant/sub
spring into existence

$ perl -MFcntl -le 'print &F_SETLK;print "defined" if defined
&F_SETLK'
13

and it still seems not to be defined.

Have I misunderstood the above snippet of perldoc?

Peter
 
B

Brian McCauley

Peter Michael said:
can anyone please explain to me why subroutines resulting
from constants imported with Exporter are not considered
to be defined?

This is INSNHO a bug in Perl.

As a work-round use exists() rather than defined().
Thanks for any explanations.

It has something to do with a bit of DWIMery what happens if you take
a reference to function that has not yet been defined. This DWIMery
exists so that you can export autoloaded functions.

Consider:

sub one { 'one' };
sub foo { 'zero' };
my $bar = \&foo;
print \&foo,$bar; # Prints the same thing twice
*foo = \&one; # Emits redefined warning
print $bar->(); # Prints zero
print \&foo,$bar; # Prints different things
eval "sub foo { 'two' }"; # Emits redefined warning
print $bar->(); # Still prints zero
print 0+defined(&$bar); # Prints 1

All that seems in line with how one expects hard code references to
behave.

Now consider:

sub one { 'one' };
my $bar = \&foo; # &foo does not yet exist
print \&foo,$bar; # Prints the same thing twice
*foo = \&one;
print \&foo,$bar; # Prints different things
print $bar->(); # Prints one
eval "sub foo { 'two' }"; # Emits redefined warning
print $bar->(); # Prints two

The supposedly hard code reference $bar is actually behaving as if it
were a symbolic reference to &main::foo.

However in this case...

print 0+defined(&$bar); # Prints 0

.... and this as I said before, IMNSHO, is a bug in Perl. It should
print 1.

--
\\ ( )
. _\\__[oo
.__/ \\ /\@
. l___\\
# ll l\\
###LL LL\\
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,579
Members
45,053
Latest member
BrodieSola

Latest Threads

Top