Symbol tables

J

Josef Moellers

Hi,

I want to define a large set of almost identical functions:

sub name {
return $_[0]->{name};
}
with varying "name"s.

I thought I'd be clever and do
foreach my $f ("name") {
$PACK::{$f} = sub { return $_[0]->{$f}; }
}

As long as I do it in one source file, it works:

-8<-8<-8<-8<-8<-8<-8<-8<-8<-8<-8<-8<-
#! /usr/bin/perl

use warnings;
use strict;
# use FAT;

package FAT32;

use warnings;
use strict;

sub func1() {
print "Here is FAT32::func1\n";
}

$FAT32::{func2} = sub { print "Here is FAT32::func2\n"; };

1;

package main;

FAT32::func1();
FAT32::func2();

exit 0;
-8<-8<-8<-8<-8<-8<-8<-8<-8<-8<-8<-8<-
Output:
Here is FAT32::func1
Here is FAT32::func2

But when I put the package FAT32 into a separate file ("FAT.pm"), I get
Here is FAT32::func1
Undefined subroutine &FAT32::func2 called at test.pl line 23.

Is there any camel-dung I can put onto my hash assignment to make it
work cross-file?

Josef
 
A

Anno Siegel

Josef Moellers said:
Hi,

I want to define a large set of almost identical functions:

sub name {
return $_[0]->{name};
}
with varying "name"s.

I thought I'd be clever and do
foreach my $f ("name") {
$PACK::{$f} = sub { return $_[0]->{$f}; }
}

As long as I do it in one source file, it works:

-8<-8<-8<-8<-8<-8<-8<-8<-8<-8<-8<-8<-
#! /usr/bin/perl

use warnings;
use strict;
# use FAT;

package FAT32;

use warnings;
use strict;

sub func1() {
print "Here is FAT32::func1\n";
}

$FAT32::{func2} = sub { print "Here is FAT32::func2\n"; };

1;

package main;

FAT32::func1();
FAT32::func2();

exit 0;
-8<-8<-8<-8<-8<-8<-8<-8<-8<-8<-8<-8<-
Output:
Here is FAT32::func1
Here is FAT32::func2

But when I put the package FAT32 into a separate file ("FAT.pm"), I get
Here is FAT32::func1
Undefined subroutine &FAT32::func2 called at test.pl line 23.

Is there any camel-dung I can put onto my hash assignment to make it
work cross-file?

To answer the last question first, if you use

*FAT32::func2 = sub { print "Here is FAT32::func2\n"; };

or just "*func2 = ........." in package FAT32, it works as expected
either way. I think that is also the more common way to assign to
a glob.

Otherwise I would also have expected your code to work. Something fishy
is going on here. Even the one-file version fails if you put the stash
assignment in a BEGIN block. On the other hand, the two-file version
works when you change "use FAT" to "require FAT". So it appears that
the assignment to %FAT32:: can't happen at compile time and have full
effect.

On the other hand, if you stick with "$FAT32::{func2} = ....", it
is enough to access *FAT32::func2 in some other way before calling
it as a function. So

my $y = *FAT32::func2; # $y is nowhere used again
FAT32::func2();

calls func2 successfully. The assignment can also be in the library
file.

Functions have a more complicated set of flags than other variables in
that they can be declared without being defined. I suppose that direct
assignment to the stash somehow doesn't treat those flags right.

Anno
 
J

Josef Moellers

Anno said:
Josef Moellers said:
Hi,

I want to define a large set of almost identical functions:

sub name {
return $_[0]->{name};
}
with varying "name"s.

I thought I'd be clever and do
foreach my $f ("name") {
$PACK::{$f} = sub { return $_[0]->{$f}; }
}

As long as I do it in one source file, it works:

-8<-8<-8<-8<-8<-8<-8<-8<-8<-8<-8<-8<-
#! /usr/bin/perl

use warnings;
use strict;
# use FAT;

package FAT32;

use warnings;
use strict;

sub func1() {
print "Here is FAT32::func1\n";
}

$FAT32::{func2} = sub { print "Here is FAT32::func2\n"; };

1;

package main;

FAT32::func1();
FAT32::func2();

exit 0;
-8<-8<-8<-8<-8<-8<-8<-8<-8<-8<-8<-8<-
Output:
Here is FAT32::func1
Here is FAT32::func2

But when I put the package FAT32 into a separate file ("FAT.pm"), I get
Here is FAT32::func1
Undefined subroutine &FAT32::func2 called at test.pl line 23.

Is there any camel-dung I can put onto my hash assignment to make it
work cross-file?


To answer the last question first, if you use

*FAT32::func2 = sub { print "Here is FAT32::func2\n"; };

or just "*func2 = ........." in package FAT32, it works as expected
either way. I think that is also the more common way to assign to
a glob.

That does work, but I need to define some 10 functions that way and I'd
likie to put that into a loop and using the typeglob thing doesn't allow
me to put a variable where func2 is.
Otherwise I would also have expected your code to work. Something fishy
is going on here. Even the one-file version fails if you put the stash
assignment in a BEGIN block. On the other hand, the two-file version
[ ... ]

It appears that it doesn't work with "use" but it does work with
"require"! Putting a BEGIN block around the require also doesn't work,
so it seems to be the BEGIN block that causes me headaches.
I can live with require-ing the module rather than use-ing it.

If anyone has more ideas, I'd be gratefull.

As the example suggests, I'm trying to handle FAT partitions (FAT32 for
the beginning).
 
A

Anno Siegel

Josef Moellers said:
Anno said:
Josef Moellers <[email protected]> wrote in comp.lang.perl.misc:

[...]
[...]
To answer the last question first, if you use

*FAT32::func2 = sub { print "Here is FAT32::func2\n"; };

or just "*func2 = ........." in package FAT32, it works as expected
either way. I think that is also the more common way to assign to
a glob.

That does work, but I need to define some 10 functions that way and I'd
likie to put that into a loop and using the typeglob thing doesn't allow
me to put a variable where func2 is.

Without strict refs you can:

for my $x ( qw( gaga blub huhu) ) {
no strict 'refs';
*{ $x} = sub { print "I'm $x\n" };
}
Otherwise I would also have expected your code to work. Something fishy
is going on here. Even the one-file version fails if you put the stash
assignment in a BEGIN block. On the other hand, the two-file version
[ ... ]

It appears that it doesn't work with "use" but it does work with
"require"! Putting a BEGIN block around the require also doesn't work,
so it seems to be the BEGIN block that causes me headaches.

Yes, I pointed that out. Doing it at compile time seems to be the
problem.
I can live with require-ing the module rather than use-ing it.

If anyone has more ideas, I'd be gratefull.

A bunch of similar function is an invitation to consider a dispatch table
(a hash of coderefs). No problems defining these, but of course the
calls look different.

Anno
 

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,580
Members
45,055
Latest member
SlimSparkKetoACVReview

Latest Threads

Top