Re: $object->UnrelatedPackage::some_subroutine() (not for me)
by tye (Sage) on Feb 18, 2005 at 05:13 UTC
|
Interesting. I was just trying to use that a couple of days ago. It didn't work on the several platforms I tried, though I rarely have 5.8 or later to use anywhere:
$ perl -e "Lie->Pkg::Meth()"
Can't locate object method "Meth" via package "Pkg::Meth" at -e line 1
+.
$
Notice it tried to look for Pkg::Meth::Meth() not Pkg::Meth().
No, I haven't looked any further. It was easy enough to work around, either as you noted or, better, using can(). And, no, it didn't work with a blessed object any better than it did with a class name.
Update: The two copies of Perl I have handy right now are both 5.6.1 (Zaurus Linux and FreeBSD) and they both have this bug.
| [reply] [d/l] |
|
|
Hmm. Your example works for me ( v5.8.1-RC3 built for darwin-thread-multi-2level):
$ perl -e 'Lie->Pkg::Meth()'
Can't locate object method "Meth" via package "Pkg" (perhaps you forgo
+t to load "Pkg"?) at -e line 1.
Is this a new or unstable feature?
I checked 5.8.1-RC3 (works), 5.8.0 (works), 5.6.1 (works).
And contrary to what I thought, you do not have to use a blessed reference, a package name is fine as well. It also works with a string scalar:
$ perl -e '$a = "Lie"; $a->Pkg::Meth()'
Can't locate object method "Meth" via package "Pkg" (perhaps you forgo
+t to load "Pkg"?) at -e line 1.
But not with other types of parameters (that cannot qualify as class name or object instance):
$ perl -e '$a = []; $a->Pkg::Meth()'
Can't call method "Pkg::Meth" on unblessed reference at -e line 1.
$ perl -e '$a = 123; $a->Pkg::Meth()'
Can't call method "Pkg::Meth" without a package or object reference at
+ -e line 1.
| [reply] [d/l] [select] |
|
|
The error message is wrong (in version 5.6.1), but the feature works perfectly well if you call a method that really exists:
perl -e 'package Pkg; sub Meth{print "hello\n"} package main; Lie->Pkg
+::Meth'
hello
| [reply] [d/l] |
|
|
| [reply] |
Re: $object->UnrelatedPackage::some_subroutine()
by stvn (Monsignor) on Feb 18, 2005 at 14:39 UTC
|
Interesting yes, but IMO an all around bad idea. Not only does it cause confusion as to what $dbh is, it also causes confusion as how the SomeDatabaseStuff package fits into everything. As far as I am concerned, this is basically only useful as an obfuscation technique, and should never be used in real code.
*sigh* and people wonder why Java programmers think perl is not really OO (as if Java was really pure OO too, but that is another discussions all together).
| [reply] [d/l] [select] |
|
|
Interesting yes, but IMO an all around bad idea. Not only does it cause confusion as to what $dbh is, it also causes confusion as how the SomeDatabaseStuff package fits into everything. As far as I am concerned, this is basically only useful as an obfuscation technique, and should never be used in real code.
Hmm. I was going to mention this pattern in the next version of DBIx::ProcedureCall. That module gives you auto-generated wrapper subroutines for database stored procedures. It does not use object orientation, just creates plain old functions. All these functions take a DBI handle as their first parameter:
# create wrapper subroutines for the Oracle
# PL/SQL package MyPackage
use DBIx::ProcedureCall qw ( MyPackage:package );
# call a function in that package
# (passing in the DBI handle to use)
my $result = MyPackage::my_function( $dbh, 123, 456);
I am unhappy with having to pass in $dbh every time.
In my own use of the module I have some custom code to
obtain the handle automatically, but this is application-specific and cannot be included in the module (although the module could be refactored a little to allow everyone to extend it in this fashion).
So I was thinking to use the strange syntax we are currently discussing to at least visually separate $dbh from the "real" parameters (that get passed to the subroutine). This probably also helps as a reminder not to forget that first parameter.
my $result = $dbh->MyPackage::my_function( 123, 456);
Of course, this looks like a method call on $dbh, which it is not. There is really no OO going on here, although it does look like it.
On the other hand, OO considerations aside, I liked the way how this makes calling a stored procedure look similar to doing a select statement (or other DBI operations).
my $result = $dbh->selectrow_arrayref('select * from blah');
I'll probably drop the idea because the syntax is too confusing.
| [reply] [d/l] [select] |
|
|
Thank you for dropping it.
If you really want to avoid passing in the dbh all the time, you're crying out for an object. Your object would more or less just store the dbh (maybe there's other things, too, that make sense for your package, I don't know, I don't use Oracle). Then it would be called via $obj->my_function(123,456) as the $obj created would be, presumably, blessed into MyPackage. I'm sure someone here could help with the design in more detail.
If I were ever to use Oracle, and I happened upon your module, and you were asking people to use this style, I would have serious doubts as to the reliability of the module, and, if I were to use it anyway, I sure as heck would not be using this syntax. It really is, IMO, that bad.
Now, if someone were to use it in a complex, multi-package obfu, that would be different. "Can you trace this program without running it through the debugger or the deparser?" Here the goal is unreadable code. But my production code using your module ... that needs to be maintainable, and $dbh->Mypackage::my_function(123, 456) is not it.
(Of course, I'm also quite partial to object wrappers around the dbh object ... having put one of those on CPAN myself ;->)
| [reply] [d/l] [select] |
|
|
| [reply] |
|
|
So I should stop using SUPER and should definitely avoid TheDamian's NEXT?
Of course not.
SUPER:: is part of perl's OO system, and a built in pseudo-package. So as far as I am concerned, it is a different story.
As for NEXT, thats up to you if you want to use it. No doubt that TheDamian knows what he is doing, but that's a pretty crazy module. Personally I just try to avoid designing anything which would need it in the first place.
However, what the OP was actually talking about was basically abusing a hole in perl's module/object system (at least thats what I see it as). The OP is actually talking about bascially using this to allow any random blessed object to become the first argument in a function, not a method. This is different from the controlled method dispatching of SUPER and NEXT.
| [reply] [d/l] |
|
|
|
|
|
Re: $object->UnrelatedPackage::some_subroutine()
by itub (Priest) on Feb 18, 2005 at 14:21 UTC
|
Here's what perlobj says:
If you need to, you can force Perl to start looking in some other package:
my $barney = MyCritter->Critter::find("Barney");
$barney->Critter::display("Height", "Weight");
Here "MyCritter" is presumably a subclass of "Critter" that defines its own versions of
find() and display(). We haven't specified what those methods do, but that doesn't matter
above since we've forced Perl to start looking for the subroutines in "Critter".
As a special case of the above, you may use the "SUPER" pseudo-class to tell Perl to start
looking for the method in the packages named in the current class's @ISA list.
Personally I don't like the style you are suggesting, because the use of this syntax suggests that DBI is a subclass of SomeDatabaseStuff (which would be a class, with my_funny_sql being a method), causing confusion. | [reply] [d/l] |
Re: $object->UnrelatedPackage::some_subroutine()
by Courage (Parson) on Feb 18, 2005 at 17:45 UTC
|
More than that: it is quite common for me to use $widget->$methodname(@parameters); inside Tcl::Tk code.
Initially I used "eval" to find out method name but was very glad to discover this nifty feature, which makes implementation faster, strictier and safer.
In my case there were some non-trivial places with SUPER and inheritance due to heavy AUTOLOADING with further defining of newly created subroutine, but those were easy to implement
:) | [reply] [d/l] |
|
|
Random obscure trick for you:
my $obj = bless {};
my $method_name = sub {"Just another Perl hacker,\n"};
print $obj->$method_name();
I've used this when dealing with code that used the above trick to get a custom result without having to go and create a special method for it.
Incidentally if you're using heavy AUTOLOADING, then you're probably better off assigning closures to typeglobs and getting rid of most of your AUTOLOADs. Not necessarily, but it tends to work well in my experience. | [reply] [d/l] |
|
|
I've used this when dealing with code that used the above trick to get a custom result without having to go and create a special method for it.
This is fine for a quick and dirty solution, but I would be wary of using it for anything else.
Perl's object system is somewhat broken as it is, so abusing it like this is just (IMO of course) a bad idea.
| [reply] |
|
|
Thanks for that knowledge bit.
In my particular case this trick will not mess a program, because I use it inside AUTOLOAD so coderefs should not pass through.
But...let's see, you can call
$Tcl::Tk::Widget::AUTOLOAD=sub{print 'tricky hacky sub'};
Tcl::Tk::Widget::AUTOLOAD($object)
Accidentally, it still not pass through as in that AUTOLOAD I see:
my $method = $Tcl::Tk::Widget::AUTOLOAD;
# Separate method to autoload from (sub)package
$method =~ s/^(Tcl::Tk::Widget::((MainWindow|$ptk_w_names)::)?)//
or die "weird inheritance ($method)";
But I get your point: I should closer revise that module for
similar things.
Also, in my case, in Tcl::Tk module AUTOLOAD is used to redirect a method to Tcl/Tk system, so it is not OO trick but rather some kind of redirecting methods to Tcl/Tk.
PS. I was talking about Tcl::Tk as I do not have anything other resembling OO | [reply] [d/l] [select] |
|
|
Re: $object->UnrelatedPackage::some_subroutine()
by ihb (Deacon) on Feb 21, 2005 at 12:31 UTC
|
_foo($self => $a, $b);
Works well for me.
ihb
See perltoc if you don't know which perldoc to read!
| [reply] [d/l] |