Another problem that would have been solved with use strict. The problem is that the foo subroutine is not defined until the end of the definition, so your foo of the last line of the subroutine is compiled as a simple bareword text string constant instead of a recursive call. You get the initial call because your foo outside the subroutine call is in fact after the subroutine is defined.
| [reply] |
<hang head in shame>
you're right of course adding () to the bareword foo made the problem go away, I though I had found the reason a bigger program that does much the same thing was failing it however report in $@ it however already has the () because two parameters are being passed to it, it sets $@ to
Can't call method "gm" without a package or object reference at (eval 2) line 99.
which leads me to believe now it's not the same problem at all..well that and there is a use strict in that one and it doesn't complain.
| [reply] |
my $e = 'my $i=0;
sub foo{
print "$i foo\n";
if ($i < 10){
$i++;
print "calling foo\n";
foo();
}
}
foo;';
eval "$e";
print $@,"\n";
Use strict would have told you this.
Joost.
| [reply] [d/l] [select] |
The output I get disagrees with what you report - you did run this with warnings enabled, didn't you? The first piece of output I see is:
Unquoted string "foo" may clash with future reserved word at (eval 1
+) line 8.
.. which makes is clear (to me, at least) that the bare foo in the if block is being interpreted as an "unquoted string", not as a subroutine call. Putting parens after it makes it an unambiguous subroutine call, satisfies the warning, and gives your expected output.
Hugo | [reply] [d/l] [select] |
use strict;
use warnings;
my $e = "foo(0)";
eval $e;
sub foo {
my $i = shift;
print "$i foo\n";
if ($i < 10){
$i++;
print "calling foo\n";
foo($i);
}
}
Other than the direct issue others already pointed out, there is two other style things:
- $i is not well scoped. You never define a variable with a scope even slightly bigger than its need. In case, $i shall be defined within the foo() function, and be passed as a parameter when it calls itself.
- It might seems okay for a demo, but define a sub in a string is not quite a good idea.
Your guess that it has something to do with multithreading is... as multithreading will not help in this case. | [reply] [d/l] |
Perl syntax is complexer than we think, since simple things can have multiple means. A word, in your case "foo", declared as it was, can be:
foo = sub foo {}
foo = string "foo"
foo = IO handler *foo
foo = constant, that actually is: sub foo { "constant" }
So, when the Perl syntax is parsed, first it will check if we have a sub with that name, if not, it will treat it as a string. As you can see, in your code, sub foo will return the string "foo".
Next time, when calling a function, always use () or &:
foo()
# or
&foo # that is the same of foo(@_)
# or just to be explicit:
&foo()
Take a look in perlsub... And http://perldoc.com is your friend.
Now about the messages of the "use strict" & "use warning" corporation, forget, since know that we need to use that doesn't means that we are goo programmers. There's a lot of things that we can't do with all the strict options enabled, and with all the warnings enabled. And Perl is here to let the developer to be free.
But use at least "use strict qw(vars)" will save you a lot of time.
Graciliano M. P.
"Creativity is the expression of the liberty".
| [reply] [d/l] [select] |
guess this would work.. some small changes.. not too complex
$e = "my \$i=0;
sub foo{
print \"\$i foo\\n\";
if (\$i < 10){
\$i++;
print \"calling foo\\n\";
&foo;
}
}
&foo\;";
eval "$e";
print $@
tc,
Garry | [reply] [d/l] |
Note that &foo will send the same arguments received by the function, since &foo is the same to write foo(@_), and is not the same of foo()!
Graciliano M. P.
"Creativity is the expression of the liberty".
| [reply] |