Re: Sub calling sadness
by John M. Dlugosz (Monsignor) on Mar 08, 2008 at 11:33 UTC
|
Wow, lots of varied answers.
Let me distill the correct answer from the various posts.
ThatPackage::blah is not defined as a sub when the call to ok is compiled, because you coded require instead of use. I don't know if that is something else you should look into, or an artifact of your testing framework.
I'm not sure, but I think use strict 'refs' would spot the problem. Why don't you have use strict at the top of your file?
So, the contents of $bar is taken as a package name at run-time (think new Blah; vs. $x="Blah"; new $x;), and the white space is a problem at this time. I don't know why it spotted it at "compile time" unless it has something to do with the constant optimizer.
Anyway, change the require to use, and then it will behave as greedy arguments to a function call without parens, since it knows that is a function.
—John writing from 西安 (Xi'an), China
Edited 10-March re correction from ikegami (writing from 昆明 (Kunming)) | [reply] [Watch: Dir/Any] [d/l] [select] |
|
Small correction:
"So, the contents of $bar is taken as a method name at run-time"
should be
"So, the contents of $bar is taken as a class name or object reference at run-time" (ThatPackage::blah would used as the method name: <<Can't call method "ThatPackage::parse" without a package or object reference>>)
| [reply] [Watch: Dir/Any] [d/l] |
|
| [reply] [Watch: Dir/Any] [d/l] [select] |
Re: Sub calling sadness
by ikegami (Patriarch) on Mar 08, 2008 at 07:09 UTC
|
ok( ThatPackage::blah $foo, 'blah' );
means
ok( ThatPackage::blah($foo, 'blah') );
| [reply] [Watch: Dir/Any] [d/l] [select] |
|
| [reply] [Watch: Dir/Any] [d/l] [select] |
|
Update: I wrote the below, obviously after reading ikegami's answer above. Yet, I went on, totally wrong. The only problem with his answer was that it's a bit terse. When the sub you are calling eats the rest of the argument list, you get surprises. For example, look at print. It seems a litle silly that ok() is OK with only one argument, but it is, which hides the real problem in your code.
sorry for confusing... (e.g.:disregard the rest of this post)
It is not possible to explain the semantics of your code without access to the definition of ThatPackage. If you could include that definition, we could probably better explain what happens and why. For example, include your definition of ThatPackage::blah something like this (after verifying that it still demonstrates the problem):
use Test::More 'no_plan';
#require 'some_file_with_my_functions.pm';
package ThatPackage;
sub blah { return $_[0] =~ /hi/ }; # Does NOT demonstrate the problem
package main;
my $foo = "hi";
my $bar = " hi";
ok( ThatPackage::blah $foo, 'blah' );
ok( ThatPackage::blah $bar, 'blah2' );
ok( ThatPackage::blah($foo), 'blah3' );
ok( ThatPackage::blah($bar), 'blah4' );
cheers
| [reply] [Watch: Dir/Any] [d/l] [select] |
|
Re: Sub calling sadness
by pc88mxer (Vicar) on Mar 08, 2008 at 07:04 UTC
|
Update: For the complete story on this question, please see John's answer below. The subtlety is that perl's interpretation of the function/method call depends on whether or not the subroutine is defined when the call is compiled.
The syntax:
ThatPackage::blah $foo
is the method-object calling syntax. For instance, consider:
my $baz = []; bless $baz, "ThatPackage";
ok( blah $baz, 'blah-baz');
This will call ThatPackage::blah with first argument of $baz using object method dispatching. The object is expected to be a blessed reference (which is generally the case) or it can also be a package name. When the method is a fully qualified identifier (like ThatPackage::blah), perl will start looking in that specified package for the subroutine to execute (see the MyCritter example in man perlobj.) However, even in this case the object still must be either a blessed reference or an package name - although perl does not check to see if the package actually 'exists.' Since spaces are not allowed in package names you are getting an error when calling ThatPackage::blah $bar.
By contrast, the syntax:
ThatPackage::blah($bar)
is simple function calling syntax. In this case the subroutine ThatPackage::blah must be defined or an error will be raised.
When using method-object syntax I would say that verifying that the object at least looks like an object is a useful check to make sure that you're doing what you think you're doing.
| [reply] [Watch: Dir/Any] [d/l] [select] |
|
This will call ThatPackage::blah with first argument of $baz using object dispatching
"Object dispatching?" No, ThatPackage::blah $foo is not an indirect method call if ThatPackage::blah has been declared as a sub. It's a simple function call.
If sub blah didn't exist in ThatPackage, then it would be an indirect method call, but $baz would be used as the class name, not as an argument.
| [reply] [Watch: Dir/Any] [d/l] [select] |
|
My point is simply that when you use the syntax ThatPackage::blah $foo, perl treats it as a method invocation and expects $foo to look like an 'object' (either a blessed reference or a package name), and this is why the OP is getting the error.
| [reply] [Watch: Dir/Any] [d/l] [select] |
|
|
| [reply] [Watch: Dir/Any] |
Re: Sub calling sadness
by FunkyMonk (Chancellor) on Mar 08, 2008 at 11:12 UTC
|
require isn't executed at compile time and if it was your problem goes away.
Either wrap your require in a BEGIN block, or use some_file_with_my_functions instead.
BEGIN {require 'some_file_with_my_functions.pm' }
#or
use some_file_with_my_functions; # you may need to "use lib '.'"
| [reply] [Watch: Dir/Any] [d/l] [select] |