Re: How to export multiple packages in one file to another Perl program?
by daxim (Curate) on Oct 04, 2012 at 15:25 UTC
|
Constants belong to a package and do not pass down inheritance, so this is not suitable for OO. You want read-only attributes.
package Object2;
use Moose;
has 'some_attr', is => 'ro', default => 42;
##################
package main;
my $o = Object2->new;
$o->some_attr; # returns 42
| [reply] [d/l] |
Re: How to export multiple packages in one file to another Perl program?
by Anique (Acolyte) on Oct 04, 2012 at 15:00 UTC
|
As far as I understand it, the idea of using OO is that you do not export anything from within your classes
That said, for each package where you want to export something, you will need to use Exporter(); within the package
| [reply] [d/l] |
|
Well I do use exporter for the non-object oriented code already and it works. I even have 'sections' I can export like :date and :maths
But I run into trouble importing any objectt oriented parts
I have to use use STDLIB; to get the library file read, but how do I get the code for package OBJECT1 read?
| [reply] [d/l] |
Re: How to export multiple packages in one file to another Perl program?
by Tanktalus (Canon) on Oct 05, 2012 at 03:34 UTC
|
"How" really depends on what you're trying to accomplish. Generally, I try to avoid this, but it's definitely not always possible.
1. As far as I'm aware, you can't export my variables. Use our instead. The issue here is that my variables are lexical variables, and to export a variable it must be global. (Variables created with our are also lexical, but they're aliases to global variables in the package in which the our occurred. If that's confusing, as long as you only have one package per file then it's roughly the same thing as "it declares a global variable".)
2. Don't put more than one package in the same file. Really, don't. Yes, some people do it. I even do it. But if you're getting confused by it, don't. I only do it when it's a small hidden package that I don't expose to anyone. That sounds to be about the opposite of what I interpret you're trying to explain that you're doing. If that sounds like someone is confused, it's because I am.
3. You don't export packages. use STDLIB qw(OBJECT1) doesn't make any sense when OBJECT1 is a package.
4. Package names are generally TitleCase, not ALLUPPERCASE, even if IT_HAS_UNDERSCORES. Constants are often all uppercase, but not package names.
5. Only the "primary" package in a file gets to export stuff. While this is not technically true, it's close enough. When I "use STDLIB", only STDLIB's import gets called. That means either STDLIB's import needs to be super fancy, or I can only import stuff from the STDLIB package.
6. The "1;" is a file-level thing. So it's only needed once at the end of the entire file.
7. XY Problem. What are you really trying to do? What interface are you trying to provide? If it's simply that someone can say my $obj = OBJECT1->new(), then you don't need to export anything. If it's that you want them to say my $obj = OBJECT1->new($OBJ1_CONSTANT1), consider using strings instead, or multiple constructors, e.g., my $obj = OBJECT1->new_with_const1(). Ok, that last one isn't a good name, but neither is OBJ1_CONSTANT1, so I can't suggest a better name.
8. Oh, and "my OBJ1_CONSTANT1;" doesn't make any sense. You're missing the sigil, so I'm not sure what type of constant you're going for here.
9. Once you've separated everything into separate files, take a look at Import::Into. I've used this to import from module X when doing "use Y;". Works pretty good so far, though I can imagine some places where even that won't be sufficient (but we're talking about arcane stuff, and I'd encourage avoiding said arcane stuff).
Hope that helps.
| [reply] [d/l] [select] |
Re: How to export multiple packages in one file to another Perl program?
by choroba (Cardinal) on Oct 04, 2012 at 15:07 UTC
|
What do you mean by an OO constant?
| [reply] |
|
I have some methods that take optional parameters like this:
$OBJ1_SORT_BY_SIZE
$OBJ1_SORT_BY_DATE
$OBJ1_SORT_BY_USER
I want these labels exported.
Of course I could create different methods for each label but prefer to have one sort method taking additional parameters
So OO constant is a constant used by the object but that needs be known outside the object
| [reply] |
Re: How to export multiple packages in one file to another Perl program?
by sundialsvc4 (Abbot) on Oct 04, 2012 at 16:09 UTC
|
First of all, I suggest that each file should contain one package.
If you do need to publish constants, then I suggest that you surf to http://search.cpan.org and search for “constants” to find some good ideas to copy. In general, look for a substantial package there and notice how they do it.
| [reply] |
|
| [reply] |
Re: How to export multiple packages in one file to another Perl program?
by BrowserUk (Patriarch) on Oct 05, 2012 at 10:10 UTC
|
package MyObjs;
use strict;
use warnings;
use enum qw[ :MOError=0 One Two Three Four Five ];
sub import {
my $self = shift;
my $caller = caller();
for( @_ ) {
if( /^:MO/ ) {
no strict; no warnings;
*{ "$caller\:\:MOError$_" } = *{ "MOError$_" } for qw[ One
+ Two Three Four Five ];
}
elsif( /^:O1/ ) {
no strict; no warnings;
*{ "$caller\:\:O1Error$_" } = *{ "Object1\:\:O1Error$_" }
+for qw[ One Two Three Four Five ];
}
elsif( /^:O2/ ) {
no strict; no warnings;
*{ "$caller\:\:O2Error$_" } = *{ "Object2\:\:O2Error$_" }
+for qw[ One Two Three Four Five ];
}
else {
die "Unknown export $_";
}
}
}
package Object1;
use enum qw[ :O1Error=100 One Two Three Four Five ];
package Object2;
use enum qw[ :O2Error=200 One Two Three Four Five ];
1;
And a script that imports from that: #! perl -slw
use strict;
use MyObjs qw[ :MO :O1 :O2 ];
print for MOErrorOne, O1ErrorThree, O2ErrorFive;
__END__
C:\test>t-MyLib.pl
0
102
204
NOTE: The use of the enum module is not germane to this working. Any subs can be exported including normal subs and those generated by constant etc.
With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
"Science is about questioning the status quo. Questioning authority".
In the absence of evidence, opinion is indistinguishable from prejudice.
RIP Neil Armstrong
;
| [reply] [d/l] [select] |
|
Thanks very much. I see now that one has to great lengths to achieve this, I might as well seperate my files into different files for each...
| [reply] |
|
I see now that one has to great lengths to achieve this,
Hm. When I compare that single import function with the guts of Exporter, I know which one I consider "great lengths".
But if you prefer to use a module, you should consider the latter's export_to_level() function.
With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
"Science is about questioning the status quo. Questioning authority".
In the absence of evidence, opinion is indistinguishable from prejudice.
RIP Neil Armstrong
| [reply] [d/l] |
Re: How to export multiple packages in one file to another Perl program?
by Wcool (Novice) on Oct 05, 2012 at 08:31 UTC
|
Thanks for all the replies.
I know about the MixedCase notation, I use it myself. The use of abstract variable names and uppercase was only to indicate it could be any class name or variable.
Let me rephrase the problem:
Let's say I have a OO package called MyFiles which maintains some sort of list of files and it supports 3 ways of sorting. $BY_SIZE, $BY_USER, $BY_DATE.
I could code 3 sort methods, or 1 sort method taking an extra parameter to indicate how it should be sorted. If I take the 2nd approach these constants have to be exported. I know how to do that using Exporter using EXPORT_OK, and I know I don't have to export any methods.
Something like
package MyFile
require Exporter;
our @ISA = qw(Exporter);
our $BY_SIZE = 0;
our $BY_USER = 1;
our $BY_DATE = 3;
@EXPORT_OK = qw(
$BY_SIZE
$BY_USER
$BY_DATE
);
But I have multiple packages in one .pm file. And now I don't seem to be able to do this.
If you say it is bad practice to have 1 method, consider than an object that returns a specific error message number.
In that case also you would like to export the possible values of the error number as the programmer would be able to use that predefined value in his code rather than some vague number. In C you would put these values in a .h file.
Considering the replies it seems that everyone recommends seperate files for each package. Something I find cumbersome for distribution. But it seems I have no choice. | [reply] [d/l] |
|
"In C you would put these values in a .h file."
In C, you wouldn't have multiple namespaces. That's the primary difference here.
In C++, if memory serves, you could have multiple namespaces and then in your .cpp (or .cxx or whatever) file, you would have using std; using object1; ... and there's no way to auto-import a bunch of namespaces, and doing so in the header would defeat much of the purpose of namespaces (they don't export just small pieces like we can in Perl).
And, in my experience, one tarball isn't any more cumbersome with one file in it or a hundred. :-) With very very few exceptions, I would say targeting a single file for deployment is misguided and/or optimistic. You'll end up with a config file, and maybe some data files (e.g., DDL for database deployment), and you'll quickly be beyond a single file anyway. May as well embrace the inevitable from the beginning. You'll also end up with code that's easier to write and maintain.
It's not that you have no choice. It's that it will take you more effort to do than if you were to follow the convention. I do have a module I just wrote for $work the other week that does something similar to what you say. But it's definitely more work to set up than following convention. I've only done this this way because of some experience with our setup that says that this will make things a little easier as we keep forgetting to import some functions that we need nearly everywhere. Normally, that's not an issue, so for everything else, it's use Module; as normal.
If you want MyThing to export the stuff from Object1, check out Import::Into. This might work:
package MyThing;
use Exporter qw(export_to_level); # no need for inheritance here.
use Import::Into; # magic
our @EXPORT = qw( $BY_SIZE $BY_DATE $BY_USER );
sub import
{
shift->export_to_level(1); # handle our exports
Object1->import::into(scalar caller); # calls Object1's import metho
+d but uses magic.
}
#...
package Object1;
# has to handle its exports here as if it were in its own file.
1;
Still more work than normal, but probably will work. Though, again, if you don't know what you're doing, this probably isn't what you want. Use separate files. | [reply] [d/l] [select] |