peculiar behaviour with prototyped routines
peculiar behaviour with prototyped routines
am 13.11.2007 09:49:37 von christian.hansel
Hi all,
Experimenting with prototyping I came across a rather peculiar and
inexplicable behaviour of routines depending on whether they are
defined in
the main file or a required library.
The following file :
#testlib.pl
#! /usr/bin/perl
sub test1(\@$) {
my @a=@{(shift)};
my $v=shift;
print "\n----------\nTest1:\n array: @a\n v:$v\n";
}
sub test2(\@$) {
my @a=@_;
my $v=pop @a;
print "\n----------\nTest2:\n array: @a\n v:$v\n";
}
print "\nin libfile..\n";
my @t1=(0,1,2,3,4,5,6,7,8,9);
test1(@t1,100);
test2(@t1,100);
1;
prints when called directly
>bash3.1 cvh@shogun::~$ perl testlib.pl
in libfile..
----------
Test1:
array: 0 1 2 3 4 5 6 7 8 9
v:100
----------
Test2:
array: ARRAY(0x804cf9c)
v:100
>bash3.1 cvh@shogun::~$
However when this file is included/required in another file the
functions
behave totally different, depending on whether the routine is called
from
where it is defined or from a higher hierarchy.
I doubt that this is intended:
The file testfile.pl
#! /usr/bin/perl
require "./testlib.pl";
print "\nin mainfile..\n";
my @t1=(0,1,2,3,4,5,6,7,8,9);
test1(@t1,100);
test2(@t1,100);
shows a reverse behaviour than that from before
bash3.1 cvh@shogun::~$ perl testfile.pl
in libfile..
----------
Test1:
array: 0 1 2 3 4 5 6 7 8 9
v:100
----------
Test2:
array: ARRAY(0x8060970)
v:100
in mainfile..
----------
Test1:
array:
v:1
----------
Test2:
array: 0 1 2 3 4 5 6 7 8 9
v:100
bash3.1 cvh@shogun::~$
As can be seen while the test1-routine does not correctly take the
provided
array parameter and instead hands @t1's first element to the second
parameter this time the second routine test2 behaves the same way
test1 did
when called from inside testlib.pl.
Can someone explain this rather peculiar behaviour or point me towards
my
mistake?. Or is this simply a bug in perl's prototyping?
Any hint or answer is greatly appreciated
CVH
Re: peculiar behaviour with prototyped routines
am 13.11.2007 12:42:26 von sheinrich
From, e.g. Tom Christiansen's "FMTEYEWTK about Prototypes in Perl" at
http://library.n0i.net/programming/perl/articles/fm_prototyp es/
"Make sure that that definition is seen by the compiler before it
compiles any calls to the function."
Because testlib.pl is required at runtime the calls to your functions
have already been compiled inside your main script and the prototypes
can not be applied anymore. The result is exactly the same as if you'd
remove the prototypes.
Mixing arrays (or hashes) with any other parameters is generally not a
good idea.
If there is only one array put it at the end, behind other scalars.
Better still, use references which is also much more efficient when it
comes to large arrays.
And you also have the choice whether or not to change the values
inside your sub.
Cheers,
Steffen
Re: peculiar behaviour with prototyped routines
am 14.11.2007 08:36:23 von christian.hansel
Hi Steffen,
Thanks for the very interesting link - a very enlightening read
indeed.
The recommendation with arrays is clear... I just needed an example.
What remains unclear, however, is your remark
> "Make sure that that definition is seen by the compiler before it
> compiles any calls to the function."
Now my question is how exactly am I supposed to that? How can I
prototype a function,
even before it is actually parsed by the compiler? Should I state 'C-
like-header-files' containing
only prototypes ?
CVH
Re: peculiar behaviour with prototyped routines
am 14.11.2007 10:05:46 von sheinrich
On Nov 14, 8:36 am, "cvh@LE" wrote:
> Hi Steffen,
>
> Thanks for the very interesting link - a very enlightening read
> indeed.
>
> The recommendation with arrays is clear... I just needed an example.
That very much means it still isn't clear, does it? ;-)
Well, just forget about the prototypes.
Expl 1, putting the one array to the end:
do_something($v, $w, @t_array);
sub do_something {
my ($scalar_1, $scalar_2, @array_in) = @_;
# @array_in now containing everything from 3rd param to end
...
}
# that means that @array_in also fetches the surplus params in a
(willing or accidental) call like
do_something($v, $w, @t_array, $xyz, %t_hash);
Expl 2, passing references:
# references have very much in common with scalars.
# for this purpose they may be seen as such and can be passed in any
order
# as long as there is no actual array like above.
do_something(\@t_array, $v, \$w, \%t_hash);
sub do_something {
my ($array_ref, $scalar_1, $scalar_ref, $hash_ref) = @_;
my $scalar_in = $$scalar_ref;
my @array_in = @$array_ref;
my %hash_in = %$hash_ref;
# $scalar_in, @array_in, and %hash_in now have the copied values
from their
# outside counterparts $w, @t_array, and %t_hash.
my $first_array_elem = $array_ref->[0];
# OR
$first_array_elem = $array_in[0];
$array_ref->[24] = 'MeaningOE'; # changes outside variable @t_array
$array_in[24] = 'MeaningOE'; # changes local copy @array_in
my $peter_value = $hash_ref->{peter};
# OR
$peter_value = $hash_in{peter};
$hash_ref->{alice} = 'down the tube'; # changes outside variable
@t_hash
$hash_in{alice} = 'down the tube'; # changes local copy @hash_in
...
}
>
> What remains unclear, however, is your remark
>
> > "Make sure that that definition is seen by the compiler before it
> > compiles any calls to the function."
This not my remark, it is cited from the page. (thus the quotes)
>
> Now my question is how exactly am I supposed to that? How can I
> prototype a function,
> even before it is actually parsed by the compiler? Should I state 'C-
> like-header-files' containing
> only prototypes ?
The message is very clear:
Forget about Perl prototypes. Don't use them and don't even think
about them.
(especially when you are still struggling with the things above.)
In your example file testfile.pl you could put the 'reuire' in a BEGIN
block:
BEGIN {
require "./testlib.pl";
}
Or you could make a proper module TestLib.pm and write
use TestLib;
In which both cases the testlib would be compiled before the function
calls in testfile.pl.
You will then observe the same output from both files.
But that's just for education. In praxis you should really stick to my
examples above.
Cheers,
Steffen