Perl classes NOT in separate files

A

Andy Glew

Q: is the below the right way to
place Perl classes "inline", near to where
they are being used?

E.g. in file bar.pl
----------------------------------
use strict
print "Code befre interleaved package/classes\n";
{
package A;
sub new { bless {}; }
sub bar { print "A"; }
}
print "Code between interleaved package/classes\n";
{
package B;
sub new { bless {}; }
sub bar { print "B"; }
}
print "Code after interleaved package/classes\n";
A->bar();
B->bar();
my $a = A->new();
my $b = B->new();
$a->bar();
$b->bar();
----------------------------------

Putting the package statement inside the block curlies
looks wierd, but I guess it's the right way.



I know the basics of Perl classes:
A class is simply a package
A package is simply a file with "packge foo" at the top
(usually one that is on your include path)

Problem: I like to use programming patterns that
create lots of light-weight classes. Typically
they derive from some base class and override
one or two methods as close as possible to the
point of use.

E.g. in C++

int foo() {
class spec1 : public base {
public: int bar() { return 45; }
} s1;
return blif( s1 );

class spec2 : public base {
public: int bar() { return 67; }
} s2;
return blif( s2 );
}

I like this pattern because it puts the
classes right next to the point of use.
(Sometimes language restrictions make you move
them outside a function, but still they are
closer to the point of use than they would be
in a separate function.)

I.e. I use classes almost as a way of creating
lambda functions.

Q: is there any way to do this in Perl?
Placing these classes in separate files
makes them much less lightweight.

I've tried putting package more than once
in a file, with no luck. E.g. how do you
"use" multiple packages from the same file?
Perl seems to tightly couple classes and files.





---
Andy Glew
PREFERRED EMAIL: (e-mail address removed)
Although I am trying to quit Outlook,
I fetchmail all of my Outlook/Exchange email
to UNIX to read
FALLBACK EMAIL: (e-mail address removed)

503-264-4119

Potential bias: employed now by Intel
past by AMD, Intel, Motorola, Gould ...
This post is personal, and is not the opinion of
any of my employers, past or present.
 
T

Tom Regner

Hi Andy,

Andy said:
Q: is the below the right way to
place Perl classes "inline", near to where
they are being used?
First guess: remove the curlies and return to a surrounding package (main in
this case):

in file bar.pl
----------------------------------
use strict
print "Code befre interleaved package/classes\n";
package A;
sub new { bless {}; }
sub bar { print "A"; }

package B;
sub new { bless {}; }
sub bar { print "B"; }

package main; # or whatever package is correct here
A->bar();
B->bar();
my $a = A->new();
my $b = B->new();
$a->bar();
$b->bar();
----------------------------------

this compiles and prints

[1117]tom@margo ~ $ perl scratch/scratch.pl
Code befre interleaved package/classes
ABAB

[...]
Q: is there any way to do this in Perl?
Placing these classes in separate files
makes them much less lightweight.

I've tried putting package more than once
in a file, with no luck. E.g. how do you
"use" multiple packages from the same file?
Perl seems to tightly couple classes and files.

You don't _use_ them with *use()*, you just *use* them ;-); I think your
only problem was putting the packages/classes in curlies and not returning
to the main-package (or superclass-package).

BTW, I like this approach for small _lambda_-Classes :)

hth,
Tom
 
A

Anno Siegel

Andy Glew said:
Q: is the below the right way to
place Perl classes "inline", near to where
they are being used?

E.g. in file bar.pl
----------------------------------
use strict
print "Code befre interleaved package/classes\n";
{
package A;
sub new { bless {}; }
sub bar { print "A"; }
}
print "Code between interleaved package/classes\n";
{
package B;
sub new { bless {}; }
sub bar { print "B"; }
}
print "Code after interleaved package/classes\n";
A->bar();
B->bar();
my $a = A->new();
my $b = B->new();
$a->bar();
$b->bar();

It's fine. If there are run-time actions in the class definition,
you may even want to make the bare block a BEGIN block.

[snip]
I.e. I use classes almost as a way of creating
lambda functions.

Q: is there any way to do this in Perl?
Placing these classes in separate files
makes them much less lightweight.

I've tried putting package more than once
in a file, with no luck. E.g. how do you

What's the problem? "No luck" is right there with "doesn't work".
Be specific.
"use" multiple packages from the same file?
Perl seems to tightly couple classes and files.

The coupling is between *modules* and file names, and it pertains
only to exportation. Perl decides which ->import method to
(try to) call by looking at the package in the use() statement.
That one corresponds to the file name.

For non-exporting packages, as are classes, the difference is
irrelevant. You can have as many of them in a file as you want.

Anno
 
T

Tom Regner

reading Anno Siegels Post (<[email protected]>), I
realized that the original code already worked as expected, I just assumed
a problem -- silly me.

So I wish I could 'unwrite' most of my original answer :)


Tom Regner wrote:
[lots of silly things]
You don't _use_ them with *use()*, you just *use* them ;-); [...]

BTW, I like this approach for small _lambda_-Classes :)

hth,
Tom

:)
kind regards,
Tom
 
A

Andy Glew

[Me, Andy Glew --- (e-mail address removed)]
What's the problem? "No luck" is right there with "doesn't work".


Sorry. The last time I tried this (multiple packages per file) was
many years ago (circa 1996-2000) on a much earlier version of Perl. I
only vaguely remember that, but I think I did

package A;
...
package B;
...

instead of

{
package A;
...
}
{
package B;
...
}

Whatever I did back then, I could not get it to work.


I realized, as I was writing the post, that embedding the package in
curly braces works. It may even work without the curly braces,
but I prefer the curly block because it allows me to embed
the package right in the code - see below.

I thought that I had fixed my post to reflect this --- to now just be
a question "Is this the best way to do multiple packages in the same
file?" But apparently I did not catch everything. Sorry.


So, is this the best way to embed packages in a file?

{
package A;
...
}
{
package B;
...
}

By the way, I like using the curly block because it allows me to place
a package in the middle of code. To my surprise

sub bar {
my $arg = shift;

package foo {
...
}

...
}

seems to work.

---

Follow-on question: what about nested packages
within the same file? Or, nested packages period.

{
package A;
...
{
package B;
...
}
}

did *NOT* do what I, well, didn't really expect
but might have hoped for.

Even though nested like this, package B is defined
in the global scope. I had been hoping that it
might be defined as A::B, i.e. nested.

I was hoping that I could use this so that
I did not have to worry as much about namespace collisions.

E.g.
{
package A;
{
package helper;
sub hello { print "A...helper\n";}
}
}
helper::hello();
{
package B;
{
package helper;
sub hello { print "B...helper\n";}
}
}
helper::hello();

Produces
B...helper
B...helper


I.e. A's helper is defined over. That is unfortunate.


--
---
Andy Glew

Potential bias: employed now by Intel
past by AMD, Intel, Motorola, Gould ...
This post is personal, and is not the opinion of
any of my employers, past or present.
 
B

Ben Morrow

Quoth Andy Glew said:
[Me, Andy Glew --- (e-mail address removed)]
print "Code befre interleaved package/classes\n";
{
package A;
sub new { bless {}; }
sub bar { print "A"; }
}
print "Code between interleaved package/classes\n";
{
package B;
sub new { bless {}; }
sub bar { print "B"; }
}
I've tried putting package more than once
in a file, with no luck. E.g. how do you
What's the problem? "No luck" is right there with "doesn't work".


Sorry. The last time I tried this (multiple packages per file) was
many years ago (circa 1996-2000) on a much earlier version of Perl. I
only vaguely remember that, but I think I did

package A;
...
package B;
...

This will work correctly.

So, is this the best way to embed packages in a file?

{
package A;
...
}
{
package B;
...
}

It's certainly what I would do, modulo making those blocks BEGIN blocks
if necessary. (Actually, following a post of (IIRC) Anno's a while back,
I'd format it like

{{

package A;

....;

}}

{{

package B;

}}

just to stop the nesting getting too deep.)
By the way, I like using the curly block because it allows me to place
a package in the middle of code. To my surprise

sub bar {
my $arg = shift;

package foo {
...
}

...
}

seems to work.

No it doesn't.

~% perl -le'package foo { 1; }'
syntax error at -e line 1, near "package foo { "
Execution of -e aborted due to compilation errors.
Follow-on question: what about nested packages
within the same file? Or, nested packages period.

{
package A;
...
{
package B;
...
}
}

did *NOT* do what I, well, didn't really expect
but might have hoped for.

Even though nested like this, package B is defined
in the global scope. I had been hoping that it
might be defined as A::B, i.e. nested.

Yes. A package statement is lexically scoped, but the packages
themselves are global. Note that the package A::B is in no sense (at the
Perl level, anyway) inside package A. It is just a package that happens
to have a :: in the middle of it's name.
I was hoping that I could use this so that
I did not have to worry as much about namespace collisions.

E.g.
{
package A;
{
package helper;
sub hello { print "A...helper\n";}
}
}
helper::hello();

If this has done what you expect this statement would have produced an
'undefined subroutine' error. It would have needed to be inside the
block.
{
package B;
{
package helper;
sub hello { print "B...helper\n";}
}
}
helper::hello();

Produces
B...helper
B...helper

I.e. A's helper is defined over. That is unfortunate.

I agree it's unfortunate. It is doubly unfortunate that there appears to
be no workaround (at least, not without using XS; with XS it's trivial,
so there may even be a module on CPAN to do it).

Note also that all top-level packages beginning with a lower-case letter
are reserved for future pragmas, so you shouldn't use them.

Ben
 
B

Brian McCauley

Andy said:
[Me, Andy Glew --- (e-mail address removed)]
print "Code befre interleaved package/classes\n";
{
package A;
sub new { bless {}; }
sub bar { print "A"; }
}
print "Code between interleaved package/classes\n";
{
package B;
sub new { bless {}; }
sub bar { print "B"; }
}
I've tried putting package more than once
in a file, with no luck. E.g. how do you
What's the problem? "No luck" is right there with "doesn't work".



Sorry. The last time I tried this (multiple packages per file) was
many years ago (circa 1996-2000) on a much earlier version of Perl. I
only vaguely remember that, but I think I did

package A;
...
package B;
...

instead of

{
package A;
...
}
{
package B;
...
}

Whatever I did back then, I could not get it to work.


I realized, as I was writing the post, that embedding the package in
curly braces works. It may even work without the curly braces,
but I prefer the curly block because it allows me to embed
the package right in the code - see below.

What you mean is you don't need to explicitly set the package back to
main. Both will of course work.
So, is this the best way to embed packages in a file?

I don't think either is universally better.
To my surprise
package foo {
...
}
seems to work.

No it does not.
Follow-on question: what about nested packages
within the same file? Or, nested packages period.

{
package A;
...
{
package B;
...
}
}

did *NOT* do what I, well, didn't really expect
but might have hoped for.

Even though nested like this, package B is defined
in the global scope. I had been hoping that it
might be defined as A::B, i.e. nested.

No all package names in Perl are absolute
I was hoping that I could use this so that
I did not have to worry as much about namespace collisions.

Yes, I've often wished there was a simple way to specify relative
package names in Perl.
 
A

Andy Glew

To my surprise
No it does not.

Sorry again, I'm full of typos.

To my surprise

sub bar {
...
{
package foo;
....
}
}

seems to work, although names in foo
are defined absolutely.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,577
Members
45,052
Latest member
LucyCarper

Latest Threads

Top