in reply to Re^6: In praise of Perl's object system.
in thread In praise of Perl's object system.

Doesn't use Exporting::Module (); plus Exporting::Module::utility_sub( ... ); address that?

It does, but it's often overly wrong long, and not very convenient; thus the fact that you can't safely import subroutines into an OO module feels like a design bug to me.

Perl 6 - links to (nearly) everything that is Perl 6.
  • Comment on Re^7: In praise of Perl's object system.

Replies are listed 'Best First'.
Re^8: In praise of Perl's object system. (OO namespaces)
by tye (Sage) on Oct 01, 2010 at 18:57 UTC

    I agree. I tend to solve this problem by having a namespace just for methods (sometimes one namespace just for class methods and another just for object methods). Then I write my code in an implementation namespace that is not searched for methods where I can write utility subroutines or import stuff with no worries. A simple demonstration might include:

    package Cone::Head; our $VERSION= '1.001_001'; use Cone::Head::code qw< new objectNamespace >; package Cone::Head::Object; use Cone::Head::code; # Imports all object methods (by default) 1;
    package Cone::Head::code; # ... use Devel::NamedArguments qw< parseMethodArgs >; sub objectNamespace { my( $we )= @_; return $we."::Object"; } sub new { my( $we, %args )= parseMethodArgs(@_); my $me= init( \%args ); return bless $me, $we->objectNamespace(); } # $obj->init() will say: Can't locate object method "init" via package +... sub init { ... } ...

    The main drawback I find with this scheme is that caller is woefully inadequate at introspection. A more useful version of caller would be able to tell me that Cone::Head::Beldar->newFromDB() searched for newFromDB() for the class Cone::Head::Beldar and found newFromDB() in parent class Cone::Head where it had been imported from Class::NiftyORM where it was originally called CreateObjectFromDB() but the code inside that method actually considers its default package name to be Class::NiftyORM::code. A situation simulated by the following code:

    package Class::NiftyORM::code; sub Class::NiftyORM::CreateObjectFromDB { ... } package Cone::Head; *newFromDB= \&ClassNiftyORM::CreateObjectFromDB; package Cone::Head::Beldar; @ISA= qw< Cone::Head >;

    So I'd like to be able to get the following information from something like caller:

    • Subroutine (or method) names:
      • Original definition (appears after "sub" keyword), might be undefined
      • Called as (can also be undefined)
    • Package names:
      • Default of compiled code (see prior 'package' statement)
      • Of original subroutine name (either above or appears after "sub" keyword)
      • Package (class) where sub was first searched for
      • Package (class) where sub was found (for non-method calls, same as above)

    - tye        

Re^8: In praise of Perl's object system.
by BrowserUk (Patriarch) on Oct 01, 2010 at 12:09 UTC
    but it's often overly wrong, and not very convenient; thus the fact that you can't safely import subroutines into an OO module feels like a design bug to me.

    For convenience; and to solve the problem at coding time rather than burdening your users with runtime solutions, try:

    package utils; use Exporting::Module qw[ utility_sub ]; package Your::OO::Module; use Exporting::Module (); ... utils::utility_sub(); ...

    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.
      That works nicely, as long as I'm the only one using namespace utils; if I'm not, I'll get optional nasty redefinition warnings, or worse silently overriden routines in the utils namespace, which might lead to very hard to debug errors.
Re^8: In praise of Perl's object system.
by ikegami (Patriarch) on Oct 01, 2010 at 19:02 UTC