Why can't my Perl object find its skip() method, even though I can call it as a subroutine? - perl

I'm working on a Perl module and whenever I call the skip() method I wrote in the following way:
$cursor->skip(4);
I get:
Undefined subroutine &MyModule::Cursor::skip called at t/tester.pl line 24.
(in cleanup) invalid object at t/tester.pl line 24.
When I call it like:
MyModule::Cursor::skip($cursor, 4);
Perl finds it!
Oddly, if I name "skip" anything else ("skipper", "hello"), this syntax works:
$cursor->skipper(4);
I thought maybe skip() was a "secret" reserved key word or something, but I've also got methods named sort() and next() (which I know are reserved), and those work fine.
I'd really like to name this method "skip." Does anyone know why Perl can't find it?

skip() is exported from Test::More, which you might have loaded since your executable is named t/tester.pl.
What does ref($cursor) yield you? It should be a blessed MyModule::Cursor object, but the "invalid object" error might be suggesting the object was not constructed properly.
EDIT: perldiag gives another clue: "in cleanup" signifies that a problem was encountered by the object's destructor. Assuming you don't already have a destructor in the object, create a MyModule::Cursor::DESTROY method that Data::Dumps the object to see what it looks like at this time.
A concise snippet of example code that exhibits this behaviour would be very helpful.

Without actual code, it's difficult to debug this.
Do you use MyModule::Cursor in your test code? When you replaced skip with skipper, were you calling it in exactly the same way from your test module? Are you able to use skip from a throw-away (one-liner or very short script)?
Where I'm going with this is looking for an error in your test code, rather than the module.
UPDATE: You're not doing something like declaring methods on MyModule::Cursor in two different files, are you? The error message you're getting tells me it has a blessed reference to an object of type MyModule::Cursor, so it knows about the class; but then it can't find the definition of skip. Do you happen to declare part of MyModule::Cursor in one file, and skip in another, and your test module isn't including the second file? Or do you have a syntax error somewhere around your definition of skip -- a missing semi-colon or unpaired curly brace? (But then again, why would MyModule::Cursor::skip work where $cursor->skip does not?)

Related

How to use one module in another module in perl?

Iam writing a perl script ,in which iam using a module utils.pm and in utils.pm iam using another module DB.pm in which i have a sub routine connetToDB().
in utils.pm iam writing
use DB qw (connectToDB());
and below iam calling that subroutine as
my $connection=DB::connectToDB(); (This is line 30)
it is giving an error like follows. Can someone pls help?
Undefined subroutine &DB::connectToDB called at utils.pm line 30.
you can see the DB.pm code here
The direct error in the shown code is that inside qw() you need names. The use pragma
Imports some semantics into the current package from the named module
(my emphasis). The "connectToDB()", with parentheses, is not the correct name for the subroutine. The error message simply says that it didn't find such a sub.
So just drop the parens, use DB qw(connectToDB);.
The code for the package was added to the question and here are some comments.
A similar fix is needed with your #EXPORT: you need the subroutine names (lose &).
Perhaps more importantly, you defined the sub using prototypes. Your sub is consistent with the prototype you use so I'll assume that it's done on purpose.
This is a very advanced (mis?)feature, which is very different from similar looking devices in other languages and is normally not needed. Chances are that you expect wrong things from prototypes. Go search for it. I'd advise against.
A side note: the prototype-related () and & are not a part of the subroutine name.
The last executed statement that returns in a module must return true, or code won't compile. The convention to ensure this is to put 1; at the end of the package.
Finally, you shouldn't name the module DB as that namespace is used internally by Perl. Also, such a generic name is just not good for a module -- it makes it easy to run into conflicts.
use DB qw(connectToDB);
my $connection=DB->connectToDB();
or
if you have defined a constructor "new" in DB.pm module then
my $connection=DB->new();
my $result = $connection->connectToDB();

Explain this witchcraft!!! (in Perl, with Moose and namespace::autoclean)

So these days I'm working with a project that uses Perl and Moose. I understand Moose is built on MOP. I'm not too familiar with MOP, and I've encountered something I don't understand, and I could use a theoretical explanation. Here is the module namespace::autoclean's documentation:
SYNOPSIS
package Foo;
use namespace::autoclean;
use Some::Package qw/imported_function/;
sub bar { imported_function('stuff') }
# later on:
Foo->bar; # works
Foo->imported_function; # will fail. imported_function got cleaned after compilation
So, back before I ever used Moose, the way that you called a method on an object was: the Perl interpreter would look up that method in the symbol table of the package that your object was blessed into (then, if not found, consider #ISA inheritance and the like). The way it called an imported function from within the package was: it looked up the name of the function in the symbol table of the package. As far as I've been aware to date, that means the same symbol table, either way, so this behavior should be impossible.
My initial inspection of the source was not productive. In broad terms, what is different when using Moose, MOP, and namespace::autoclean, that this sort of trickery becomes possible?
ed. To be especially clear, if I were to replace use namespace::autoclean with
CHECK { undef *Foo::imported_function }
then the Foo->bar; call described in the documentation would crash, because Foo->bar doesn't know where to find imported_function.
It's actually quite simple. For
some_sub()
some_sub is resolved at compile time. For
$o->some_method()
some_method is resolved at runtime. It cannot be done at compile-time since it depends on the value of $o.
There is nothing here that is non-standard. The line
use Some::Package qw/imported_function/;
imports imported_function into the current package, so Foo::imported_function is the same subroutine as Some::Package::imported_function. That assumes that Some::Package inherits from Exporter to do the necessary manipulation of the symbol tables.
The calls are method calls, so Foo->bar is the same as Foo::bar('Foo'). The only special thing here is that the magic that has been done by the import function from Exporter is undone at the end of compile time by namespace::autoclean.
I haven't looked at the code for this module, but since a package's symbol table is just a hash (known as a stash, for symbol table hash) it would be easy to preserve its state at one point and restore it afterwards. So I would guess namespace::autoclean takes a snapshot of the symbol table when it is loaded and the restores that state at the end of compilation time. This can conveniently be done in a CHECK block which behaves like a BEGIN block but is executed at the end of compilation and before the run starts.

How could a simple optional argument lead to data corruption?

I have a FORTRAN code with a routine:
SUBROUTINE READ_NC_VALS(NCID, RECID, VARNAME, VARDATA)
integer ncid, recid
character*(*) varname
real*8 vardata
dimension vardata(15,45,75)
etc.
I want to add some flexibility to this code, and I thought I would do it by first adding an optional flag argument:
SUBROUTINE READ_NC_VALS(NCID, RECID, VARNAME, VARDATA, how_to_calculate)
! everything the same and then ...
logical, optional :: how_to_calculate
Now, at this point, I am not even using "how_to_calculate". I am just putting it into the code for testing. So I compile the code without a hitch. Then I run it, and I get an error in the subroutine. Specifically, some of the values in the code later on are "magically" altered from what they were without that optional argument. The new values don't make sense to the logic of the code, so it exits politely with an error message. Let me stress again that at this point, I am not even using this optional argument. So then, on a lark, I go back to all the places in the source that call this routine and, even though my new argument in optional, I put in values for it in all the calls. When I do that, the code runs fine. So, what's up? How can the mere presence of an unused optional argument in a subroutine result in other data being corrupted? And how can adding input parameters for this optional argument fix things again? This is being compiled with PGI, by the way.
Any ideas? Thanks.
BTW, sorry for not providing more code. My boss might not be too happy with me if I did that. I don't make the rules; I just work here.
Optional arguments in Fortran are implemented by passing 0 (a null pointer) for each optional argument that has no value provided by the calling subroutine. Because of this subroutines that take optional arguments have to:
either have an explicit INTERFACE definition inside the calling subroutine
or be a module-level subroutine (for them interfaces are generated automatically)
If you add an optional argument to a subroutine but it neither has an interface in the caller or is not a module-level subroutine, then the compiler will not generate the right calling sequence - it will pass less arguments than expected. This could pose a problem on Unix systems, where PGI passes the length of all CHARACTER*(*) arguments at the end of the argument list (on Windows it passes the length as the next argument after the address of the string). One missing argument would shift the length arguments placement in the stack (or put them in the wrong registers on x64) leading to the incorrect length of the VARNAME string being received by READ_NC_VALS. This could lead to all sorts of ill behaviour, including overwritting memory and "magically" changing values that should not change according to the program logic.
Obviously, just adding a dummy argument to a subroutine, with or without the optional attribute, shouldn't cause any problems. What might happen, though, is that the change exposes some other problem with the code, which was already there, but didn't cause any visible bad effects.
Without any more code, all we can do is guess, which usually isn't really useful.
One thing that pops into mind is the necessity of an explicit interface, when using optional arguments. Is the code organized into modules?

Error in objective C

I am trying to run unit test whereby I am getting an warning:
'FileName' may not respond to '-failWithException:'
I wanted to know why this warning occurs and how to fix that?
Either the FileName interface does not declare the failWithException: method, or you have not imported the header file in which the interface is declared.
Whatever sort of object FileName is, the compiler can't find a method named '-failWithException' in that class. The solution is to go implement that method on that class, or to make sure the compiler can find the header file where it already is implemented.
By the way, it's a warning instead of an error because, unlike for instance Java, Objective-C allows you to manipulate classes at runtime. So while you PROBABLY have a problem there, you don't DEFINITELY have a problem, so the IDE gives you a yellow warning rather than a red error. But in your case, this is almost certainly something you need to fix.

Perl: variable scope issue with CGI & DBI modules

I've run into what appears to be a variable scope issue I haven't encountered before. I'm using Perl's CGI module and a call to DBI's do() method. Here's the code structure, simplified a bit:
use DBI;
use CGI qw(:cgi-lib);
&ReadParse;
my $dbh = DBI->connect(...............);
my $test = $in{test};
$dbh->do(qq{INSERT INTO events VALUES (?,?,?)},undef,$in{test},"$in{test}",$test);
The #1 placeholder variable evaluates as if it is uninitialized. The other two placeholder variables work.
The question: Why is the %in hash not available within the context of do(), unless I wrap it in double quotes (#2 placeholder) or reassign the value to a new variable (#3 placeholder)?
I think it's something to do with how the CGI module's ReadParse() function assigns scope to the %in hash, but I don't know Perl scoping well enough to understand why %in is available at the top level but not from within my do() statement.
If someone does understand the scoping issue, is there a better way to handle it? Wrapping all the %in references in double quotes seems a little messy. Creating new variables for each query parameter isn't realistic.
Just to be clear, my question is about the variable scoping issue. I realize that ReadParse() isn't the recommended method to grab query params with CGI.
I'm using Perl 5.8.8, CGI 3.20, and DBI 1.52. Thank you in advance to anyone reading this.
#Pi & #Bob, thanks for the suggestions. Pre-declaring the scope for %in has no effect (and I always use strict). The result is the same as before: in the db, col1 is null while cols 2 & 3 are set to the expected value.
For reference, here's the ReadParse function (see below). It's a standard function that's part of CGI.pm. The way I understand it, I'm not meant to initialize the %in hash (other than satisfying strict) for purposes of setting scope, since the function appears to me to handle that:
sub ReadParse {
local(*in);
if (#_) {
*in = $_[0];
} else {
my $pkg = caller();
*in=*{"${pkg}::in"};
}
tie(%in,CGI);
return scalar(keys %in);
}
I guess my question is what is the best way to get the %in hash within the context of do()? Thanks again! I hope this is the right way to provide additional info to my original question.
#Dan: I hear ya regarding the &ReadParse syntax. I'd normally use CGI::ReadParse() but in this case I thought it was best to stick to how the CGI.pm documentation has it exactly.
It doesn't actually look like you're using it as described in the docs:
https://metacpan.org/pod/CGI#COMPATIBILITY-WITH-CGI-LIB.PL
If you must use it, then CGI::ReadParse(); seems more sensible and less crufty syntax. Although I can't see it making much difference in this situation, but then it is a tied variable, so who the hell knows what it's doing ;)
Is there a particular reason you can't use the more-common $cgi->param('foo') syntax? It's a little bit cleaner, and filths up your namespace in a considerably more predictable manner..
use strict;. Always.
Try declaring
our %in;
and seeing if that helps. Failing that, strict may produce a more useful error.
I don't know what's wrong, but I can tell you some things that aren't:
It's not a scoping issue. If it were then none of the instances of $in{test} would work.
It's not the archaic & calling syntax. (It's not "right" but it's harmless in this case.)
ReadParse is a nasty bit of code. It munges the symbol table to create the global variable %in in the calling package. What's worse is that it's a tied variable, so accessing it could (theoretically) do anything. Looking at the source code for CGI.pm, the FETCH method just invokes the params() method to get the data. I have no idea why the fetch in the $dbh->do() isn't working.
Firstly, that is not in the context/scope of do. It is still in the context of main or global. You dont leave context until you enter {} in some way relating to subroutines or different 'classes' in perl. Within () parens you are not leaving scope.
The sample you gave us is of an uninitialized hash and as Pi has suggested, using strict will certainly keep those from occuring.
Can you give us a more representative example of your code? Where are you setting %IN and how?
Something's very broken there. Perl's scoping is relatively simple, and you're unlikely to stumble upon anything odd like that unless you're doing something daft. As has been suggested, switch on the strict pragma (and warnings, too. In fact you should be using both anyway).
It's pretty hard to tell what's going on without being able to see how %in is defined (is it something to do with that nasty-looking ReadParse call? why are you calling it with the leading &, btw? that syntax has been considered dead and gone for a long time). I suggest posting a bit more code, so we can see what's going on..
What version of DBI are you using? From looking at the DBI changelog it appears that versions prior to 1.00 didn't support the attribute argument. I suspect that the "uninitialized" $in{test} is actually the undef that you're passing to $dbh->do().
From the example you gave, this is not a scoping issue, or none of the parameters would work.
Looks like DBI (or a DBD, not sure where bind parameters are used) isn't honoring tie magic.
The workaround would be to stringize or copy what you pass to it, like your second and third parameters do.
A simple test using SQLite and DBI 1.53 shows it working ok:
$ perl -MDBI -we'sub TIEHASH { bless {} } sub FETCH { "42" } tie %x, "main" or die; my $dbh = DBI->connect("dbi:SQLite:dbname=dbfile","",""); $dbh->do("create table foo (bar char(80))"); $dbh->do("insert into foo values (?)", undef, $x{foo}); print "got: " . $dbh->selectrow_array("select bar from foo") . "\n"; $dbh->do("drop table foo")'
got: 42
Care to share what database you are using?
Per the DBI documentation: Binding a tied variable doesn't work, currently.
DBI is pretty complicated under the hood, and unfortunately goes through some gyrations to be efficient that are causing your problem. I agree with everyone else who says to get rid of the ugly old cgi-lib style code. It's unpleasant enough to do CGI without a nice framework (go Catalyst), let alone something that's been obsolete for a decade.
Okay, try this:
use CGI;
my %in;
CGI::ReadParse(\%in);
That might help as it's actually using a variable that you've declared, and therefore can control the scope of (plus it'll let you use strict without other nastiness that could be muddying the waters)
As this is starting to look like a tie() problem, try the following experiment. Save this as a foo.pl and run it as perl foo.pl "x=1"
use CGI;
CGI::ReadParse();
p($in{x}, "$in{x}");
sub p { my #a = #_; print "#a\n" }
It should print 1 1. If it doesn't, we've found the culprit.
I just tried your test codce from http://www.carcomplaints.com/test/test.pl.txt, and it works right away on my computer, no problems. I get three values as expected. I didn't run it as CGI, but using:
...
use CGI qw/-debug/;
...
I write a variable on the console (test=test) and your scripts inserts without a problem.
If however your leave this out, tt will insert an empty string and two NULLs. This is a because you interpolate a value into a string. This will makes a string with value of $in{test} which is undef at the moment. undef stringifies to an empty string, which is what is inserted into database.
Try this
%in = ReadParse();
but i doubt that. Are you trying to get query parameters or something?