Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Perl > Perl Misc > Problem about type glob reference

Reply
Thread Tools

Problem about type glob reference

 
 
Todd
Guest
Posts: n/a
 
      12-25-2007
I meet with a inconsistent behavior about the type glob reference
blow. Here Case3 works fine. But Case1 and Case2 file a compile error.
The difference between Case2 and Case3 is that I move the typeglob
assignment from inside SCOPE to outside SCOPE. I'm trying to
understand this, may you help me?

Case1:
#! /bin/perl -l

BEGIN {
package Foo;
sub foo { print "foo called"; }
$main::{foo} = \&foo;
}

&main::foo();

__END__
Undefined subroutine &main::foo called at - line 9.


Case2:
#! /bin/perl -l

BEGIN {
package Foo;
sub foo { print "foo called"; }
$main::{foo} = \&Foo::foo;
}

&main::foo();

__END__
Undefined subroutine &main::foo called at - line 9.

Case3:
#! /bin/perl -l

BEGIN {
package Foo;
sub foo { print "foo called"; }
}

$main::{foo} = \&Foo::foo;
&main::foo();

__END__

foo called

Thanks,
Todd
 
Reply With Quote
 
 
 
 
Todd
Guest
Posts: n/a
 
      12-25-2007


Todd wrote:
> $main::{foo} = \&foo;

I know the better one is
*main::foo = \&foo;
Or even better: use Exporter and use.

But this doesn't explain my question. Hopefully some useful hints.

Thanks,
Todd
 
Reply With Quote
 
 
 
 
Peter Scott
Guest
Posts: n/a
 
      12-25-2007
On Tue, 25 Dec 2007 05:40:29 -0800, Todd wrote:
> #! /bin/perl -l
>
> BEGIN {
> package Foo;
> sub foo { print "foo called"; }
> $main::{foo} = \&foo;
> }
>
> &main::foo();
>
> __END__
> Undefined subroutine &main::foo called at - line 9.


I only have a few minutes to spare here before my battery runs out, but
what's weird about this is (a) it works if you do something with foo()
inside the BEGIN block, and (b) the result is different on 5.10.

End the BEGIN block with, say,

foo();
or
my $x = *main::foo{CODE};

and it works. Try it on 5.10 and the error when calling &main::foo
changes to "Cannot convert a reference to CODE to typeglob".

--
Peter Scott
http://www.perlmedic.com/
http://www.perldebugged.com/

 
Reply With Quote
 
comp.llang.perl.moderated
Guest
Posts: n/a
 
      12-26-2007
On Dec 25, 7:44 am, Peter Scott <(E-Mail Removed)> wrote:
> On Tue, 25 Dec 2007 05:40:29 -0800, Todd wrote:
> > #! /bin/perl -l

>
> > BEGIN {
> > package Foo;
> > sub foo { print "foo called"; }
> > $main::{foo} = \&foo;
> > }

>
> > &main::foo();

>
> > __END__
> > Undefined subroutine &main::foo called at - line 9.

>
> I only have a few minutes to spare here before my battery runs out, but
> what's weird about this is (a) it works if you do something with foo()
> inside the BEGIN block, and (b) the result is different on 5.10.
>
> End the BEGIN block with, say,
>
> foo();


In this case, Foo::foo() is called however:

BEGIN { ...
sub foo { print "foo called by ",(caller)[0];}
foo();
}

foo called by Foo

A package declaration has lexical scope and
'main' is still undefined within BEGIN. This
though would also work:


BEGIN {
package Foo;
sub foo { print "foo called"; }
$main::{foo} = \&foo;
package main;
foo()
}

> or
> my $x = *main::foo{CODE};
>
> and it works. Try it on 5.10 and the error when calling &main::foo
> changes to "Cannot convert a reference to CODE to typeglob".
>


No idea why the later works though..

--
Charles DeRykus
 
Reply With Quote
 
Todd
Guest
Posts: n/a
 
      12-26-2007


Peter Scott wrote:
> End the BEGIN block with, say,
>
> foo();
> or
> my $x = *main::foo{CODE};
>
> and it works. Try it on 5.10 and the error when calling &main::foo


So these 2 works below:

#! /bin/perl -l
BEGIN {
package Foo;
sub foo { print "foo called"; }
$main::{foo} = \&Foo::foo;
my $x = *main::foo{CODE};
}

&main::foo();

__END__
foo called


#! /bin/perl -l
{
package Foo;
sub foo { print "foo called"; }
$main::{foo} = \&Foo::foo;
}

&main::foo();

__END__

foo called

Seems it's related to the subtle meaning of BEGIN and reference count,
can any one give a explanation about this?

-Todd
 
Reply With Quote
 
comp.llang.perl.moderated
Guest
Posts: n/a
 
      12-26-2007
On Dec 26, 6:23 am, Todd <(E-Mail Removed)> wrote:
> Peter Scott wrote:
> > End the BEGIN block with, say,

>
> > foo();
> > or
> > my $x = *main::foo{CODE};

>
> > and it works. Try it on 5.10 and the error when calling &main::foo

>
> So these 2 works below:
>
> #! /bin/perl -l
> BEGIN {
> package Foo;
> sub foo { print "foo called"; }
> $main::{foo} = \&Foo::foo;
> my $x = *main::foo{CODE};
> }
>
> &main::foo();
>
> __END__
> foo called
>
> #! /bin/perl -l
> {
> package Foo;
> sub foo { print "foo called"; }
> $main::{foo} = \&Foo::foo;
> }
>
> &main::foo();
>
> __END__
>
> foo called
>
> Seems it's related to the subtle meaning of BEGIN and reference count,
> can any one give a explanation about this?


You might be right but somehow I think there's
more to it.. including lexical package scope.
Just a simple declaration of 'main' inside
BEGIN {} works:

#! /bin/perl -l

BEGIN {
package main;
sub foo { print "foo called..."; }
}

foo();
__END__
foo called...

Note 'foo' also becomes available via 'use subs' occurring at compile
time too:

use subs 'foo';
BEGIN {
package Foo;
sub foo { print "foo called...'; }
$main::{foo} = \&Foo::foo;
# my $x = *main::foo{CODE};
}
foo();
__END__
foo called...

--
Charles DeRykus


 
Reply With Quote
 
comp.llang.perl.moderated
Guest
Posts: n/a
 
      12-28-2007
On Dec 25, 5:40 am, Todd <(E-Mail Removed)> wrote:
> I meet with a inconsistent behavior about the type glob reference
> blow. Here Case3 works fine. But Case1 and Case2 file a compile error.
> The difference between Case2 and Case3 is that I move the typeglob
> assignment from inside SCOPE to outside SCOPE. I'm trying to
> understand this, may you help me?
>
> Case1:
> #! /bin/perl -l
>
> BEGIN {
> package Foo;
> sub foo { print "foo called"; }
> $main::{foo} = \&foo;
> }
>
> &main::foo();
>
> __END__
> Undefined subroutine &main::foo called at - line 9.
>
> Case2:
> #! /bin/perl -l
>
> BEGIN {
> package Foo;
> sub foo { print "foo called"; }
> $main::{foo} = \&Foo::foo;
> }
>
> &main::foo();
>
> __END__
> Undefined subroutine &main::foo called at - line 9.
>
> Case3:
> #! /bin/perl -l
>
> BEGIN {
> package Foo;
> sub foo { print "foo called"; }
> }
>
> $main::{foo} = \&Foo::foo;
> &main::foo();
>
> __END__
>
> foo called
>


Reducing all these to a simple example:

BEGIN {
sub Foo::foo { print "foo called..."; }
$main::{foo} = \&Foo::foo; # assign ref.
}

foo(); # fails with "undef. subroutine ...


However, as noted earlier, moving the 'assign ref.' line above outside
BEGIN {} just before the foo() call works. Adding 'use vars "foo"' at
the top works too. Suprisingly so does adding '$::foo = 1' inside --
but not outside -- BEGIN {} does too.

With these diverse solutions, I suspect Perl has some heuristic about
whether to discard the glob assignment but I really doubt it's just a
ref. count.

--
Charles DeRykus
 
Reply With Quote
 
Peter Scott
Guest
Posts: n/a
 
      12-28-2007
On Fri, 28 Dec 2007 05:26:13 -0800, comp.llang.perl.moderated wrote:
> Reducing all these to a simple example:
>
> BEGIN {
> sub Foo::foo { print "foo called..."; }
> $main::{foo} = \&Foo::foo; # assign ref.
> }
>
> foo(); # fails with "undef. subroutine ...
>
>
> However, as noted earlier, moving the 'assign ref.' line above outside
> BEGIN {} just before the foo() call works. Adding 'use vars "foo"' at
> the top works too. Suprisingly so does adding '$::foo = 1' inside --
> but not outside -- BEGIN {} does too.
>
> With these diverse solutions, I suspect Perl has some heuristic about
> whether to discard the glob assignment but I really doubt it's just a
> ref. count.


It is not exactly discarding the glob assignment. Try it on 5.10 and see
what error you get.

As a p5p poster pointed out, the assignment should be:

*main::foo = \&foo;

and all is right with the world. That doesn't explain what is going on
with this code, but it does solve the OP's problem.

--
Peter Scott
http://www.perlmedic.com/
http://www.perldebugged.com/

 
Reply With Quote
 
comp.llang.perl.moderated
Guest
Posts: n/a
 
      12-29-2007
On Dec 28, 6:15 am, Peter Scott <(E-Mail Removed)> wrote:
> On Fri, 28 Dec 2007 05:26:13 -0800, comp.llang.perl.moderated wrote:
> > Reducing all these to a simple example:

>
> > BEGIN {
> > sub Foo::foo { print "foo called..."; }
> > $main::{foo} = \&Foo::foo; # assign ref.
> > }

>
> > foo(); # fails with "undef. subroutine ...

>
> > However, as noted earlier, moving the 'assign ref.' line above outside
> > BEGIN {} just before the foo() call works. Adding 'use vars "foo"' at
> > the top works too. Suprisingly so does adding '$::foo = 1' inside --
> > but not outside -- BEGIN {} does too.

>
> > With these diverse solutions, I suspect Perl has some heuristic about
> > whether to discard the glob assignment but I really doubt it's just a
> > ref. count.

>
> It is not exactly discarding the glob assignment. Try it on 5.10 and see
> what error you get.
>
> As a p5p poster pointed out, the assignment should be:
>
> *main::foo = \&foo;



Interesting, that does the trick as well. I'm
confused why the alternate *main{foo} doesn't
work as well though. *main::foo is accessed
more efficiently at compile time but $main::{foo}
won't create a new typeglob if none previously
exists. So, I'm not sure why the former should
viewed preferentially...

>
> and all is right with the world. That doesn't explain what is going on
> with this code, but it does solve the OP's problem.


It also doesn't explain why 'use vars "foo"'
or '$::foo = 1' in the BEGIN causes all to be
"right with the world"

Thanks for the info.
--
Charles DeRykus
 
Reply With Quote
 
Ben Morrow
Guest
Posts: n/a
 
      12-29-2007

Quoth "comp.llang.perl.moderated" <(E-Mail Removed)>:
> On Dec 28, 6:15 am, Peter Scott <(E-Mail Removed)> wrote:
> > On Fri, 28 Dec 2007 05:26:13 -0800, comp.llang.perl.moderated wrote:
> > > Reducing all these to a simple example:

> >
> > > BEGIN {
> > > sub Foo::foo { print "foo called..."; }
> > > $main::{foo} = \&Foo::foo; # assign ref.
> > > }

> >
> > > foo(); # fails with "undef. subroutine ...

> >

<snip: $main::{foo} outside BEGIN works>
> >
> > > With these diverse solutions, I suspect Perl has some heuristic about
> > > whether to discard the glob assignment but I really doubt it's just a
> > > ref. count.

> >
> > It is not exactly discarding the glob assignment. Try it on 5.10 and see
> > what error you get.
> >
> > As a p5p poster pointed out, the assignment should be:
> >
> > *main::foo = \&foo;

>
> Interesting, that does the trick as well.


That's unsurprising: it's the supported and documented way of doing
this.

> I'm confused why the alternate *main{foo} doesn't work as well
> though.


Huh? I think you need to read perlref again. Typeglobs don't have a foo
slot, and even if they did it would have nothing to do with any sub
named &foo in any package.

> *main::foo is accessed more efficiently at compile time but
> $main::{foo} won't create a new typeglob if none previously exists.


....which is the root of the problem. %main:: is 'just' an ordinary hash:
it doesn't know it's a symbol table, and it doesn't know it should only
contain globs. So

$main::{foo} = \&Foo::foo;

puts a subref directly in the symbol table, where a glob should be.
Unsurprisingly, this doesn't work: when perl later tries to look up
&main::foo, it can't find a typeglob for it. 5.10 gives a slightly more
helpful message than 5.8, probably because 5.10 *does* sometimes expect
to find things other than typeglobs in the symbol table. For instance:

~% perl5.8.8 -le'BEGIN{ $main::{foo} = \2 } print foo'
Undefined subroutine &main::foo called at -e line 1.
~% perl5.10.0 -le'BEGIN{ $main::{foo} = \2 } print foo'
2
~%

> > and all is right with the world. That doesn't explain what is going on
> > with this code, but it does solve the OP's problem.

>
> It also doesn't explain why 'use vars "foo"'
> or '$::foo = 1' in the BEGIN causes all to be
> "right with the world"


*Any* reference to *main::foo before perl reaches the assignment causes
$main::{foo} to be filled with a typeglob automatically. So even
removing the BEGIN fixes the problem, as when perl compiles the call to
&main::foo it creates the typeglob, so by the time it gets to the
assignment (at runtime) there is already a glob there. At that point
normal glob assignment magic kicks in.

Ben

 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
i have problem with glob.glob() in remotely directory lameck kassana Python 0 02-26-2009 09:05 AM
glob.glob unicode bug or feature Elbert Lev Python 5 08-02-2004 12:09 AM
Question about glob.glob <--newbie Sean Berry Python 3 05-04-2004 05:34 PM
RE: Bug in glob.glob for files w/o extentions in Windows Tim Peters Python 1 12-01-2003 09:22 AM
Bug in glob.glob for files w/o extentions in Windows Georgy Pruss Python 15 12-01-2003 04:04 AM



Advertisments