Perl classes NOT in separate files

Discussion in 'Perl Misc' started by Andy Glew, Dec 2, 2004.

  1. Andy Glew

    Andy Glew Guest

    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:
    Although I am trying to quit Outlook,
    I fetchmail all of my Outlook/Exchange email
    to UNIX to read
    FALLBACK EMAIL:

    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.
    Andy Glew, Dec 2, 2004
    #1
    1. Advertising

  2. Andy Glew

    Tom Regner Guest

    Hi Andy,

    Andy Glew wrote:

    > 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
    Tom Regner, Dec 2, 2004
    #2
    1. Advertising

  3. Andy Glew

    Anno Siegel Guest

    Andy Glew <> wrote in comp.lang.perl.misc:
    > 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.


    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
    Anno Siegel, Dec 2, 2004
    #3
  4. Andy Glew

    Tom Regner Guest

    reading Anno Siegels Post (<comrpg$a5f$-Berlin.DE>), 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
    Tom Regner, Dec 2, 2004
    #4
  5. Andy Glew

    Andy Glew Guest

    > > [Me, Andy Glew --- ]
    > > 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

    >

    -berlin.de (Anno Siegel) writes:
    > 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.
    Andy Glew, Dec 3, 2004
    #5
  6. Andy Glew

    Ben Morrow Guest

    Quoth Andy Glew <>:
    > > > [Me, Andy Glew --- ]
    > > > 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

    > >

    > -berlin.de (Anno Siegel) writes:
    > > 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.

    <snip>
    > 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

    --
    Every twenty-four hours about 34k children die from the effects of poverty.
    Meanwhile, the latest estimate is that 2800 people died on 9/11, so it's like
    that image, that ghastly, grey-billowing, double-barrelled fall, repeated
    twelve times every day. Full of children. [Iain Banks]
    Ben Morrow, Dec 3, 2004
    #6
  7. Andy Glew wrote:

    >>>[Me, Andy Glew --- ]
    >>>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

    >>

    > -berlin.de (Anno Siegel) writes:
    >
    >>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.
    Brian McCauley, Dec 4, 2004
    #7
  8. Andy Glew

    Andy Glew Guest

    > > To my surprise
    >
    > > package foo {
    > > ...
    > > }

    >
    > > seems to work.

    >
    > 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.


    ---

    But I'm probably wrong, and really should post
    an experiment. Won't bother, because it
    was the nesting I most wanted.
    Andy Glew, Dec 9, 2004
    #8
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Humberto Alvarez

    getting access to classes in separate vb files

    Humberto Alvarez, Jan 4, 2006, in forum: ASP .Net
    Replies:
    4
    Views:
    502
    Peter Rilling
    Jan 4, 2006
  2. EvgueniB
    Replies:
    1
    Views:
    615
    Anthony Borla
    Dec 15, 2003
  3. kelvSYC
    Replies:
    2
    Views:
    778
    Chris Uppal
    Aug 17, 2004
  4. Frank Fredstone
    Replies:
    1
    Views:
    430
    Jean-Francois Briere
    Jun 27, 2006
  5. Ò»Ê×Ê«
    Replies:
    1
    Views:
    488
    Diez B. Roggisch
    Apr 14, 2009
Loading...

Share This Page