Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl-Sensitive Sunglasses

Creating modules with OO and functional interfaces.

by BazB (Priest)
on May 14, 2002 at 11:29 UTC ( #166417=perlquestion: print w/replies, xml ) Need Help??
BazB has asked for the wisdom of the Perl Monks concerning the following question:

How would I go about creating a module that uses both OO and functional interfaces?

I tend to supply named arguments, and I get an error warning that there is an odd number of arguments in a hash assignment if I use a subroutine expecting $self as it's first argument.

I wouldn't think checking that the first argument is a reference is a solution - making pass-by-reference awkward is a Bad Thing :)

Below is a sample of _rough_ code that will only work as OO - how can it be transformed to work as a functional or OO module (like, for example - which I can't figure out :-) ).

package Foo; # use Modules; # set up @EXPORT, @EXPORT_OK etc for functional interface sub new { my $class = shift; my $self = {}; bless ($self, $class); } sub print_args { my $self = shift; my %args = @_; print $args{'foo'}, $args{'bar'}, "\n"; } package Bar; $obj = Foo->new(); $obj->Foo::print_args(foo => "Perl", bar => "Monks"); exit;


Replies are listed 'Best First'.
Re: Creating modules with OO and functional interfaces.
by broquaint (Abbot) on May 14, 2002 at 11:58 UTC
    This sort of thing is generally discouraged in the world of OO where a consistent interface to the class is fairly key[1]. The mixing of a procedural[2] interface with class/object methods is rather counter-intuitive (where's my object state kept?!?). If you look at the source of CGI you can see it implements this mixing of styles by using a 'magical' method called self_or_default() which basically gets around the fact that a method is being called as a function. However if you're deadset on implementing both styles, then perl's certainly the language to do it in ;-) Check out the code for the self_or_default() method in CGI for some pointers on how to do this (it basically checks whether it's first argument is a reference to a CGI object or not and does the right thing).


    [1] there's an interesting debate on this topic here between TheDamian and tilly
    [2] not functional, for functional + OO programming check out Haskell or OCaml

Re: Creating modules with OO and functional interfaces.
by ariels (Curate) on May 14, 2002 at 11:42 UTC

    CGI has this feature; it seems to live in the function ``<samp>self_or_default</samp>'' and maybe also ``<samp>self_or_CGI</samp>'' (both in the main <samp></samp> file). You might examine its implementation -- it checks that the first argument is a reference, or that it ``isa-CGI'' (the first test is probably just optimizing for the common case).

Re: Creating modules with OO and functional interfaces.
by particle (Vicar) on May 14, 2002 at 12:39 UTC
    CGI is a complex module for an example of providing OO and functional interfaces. check out Ben Tilly's ReleaseAction for a consise example.

    ~Particle *accelerates*

Re: Creating modules with OO and functional interfaces.
by chromatic (Archbishop) on May 14, 2002 at 14:50 UTC
    You could say:
    my $self; $self = shift if (UNIVERSAL::isa( $_[0], 'My::Object' );
    I'd rather see a procedural interface that uses a default singleton object. Under the hood, it's using the OO interface, but the actual object is hidden from users, if that's necessary.
Re: Creating modules with OO and functional interfaces.
by cfreak (Chaplain) on May 14, 2002 at 13:22 UTC

    Even though I agree with the general feeling in this thread that its not a good idea™. You could check to see if $self is a reference and if not use it as the first argument.

    Hope that helps

    Some clever or funny quote here.
Re: Creating modules with OO and functional interfaces.
by Anonymous Monk on May 14, 2002 at 21:15 UTC
    In addition to chromatic's suggestion you might want to check how many arguments you got. If you also got an odd number of arguments then you (probably) got the object.

    Needless to say, these methods are not perfect. I too advice against it.


Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://166417]
Approved by coreolyn
[karlgoethebier]: perldigious: perhaps a block if you are paranoid ;-)
[choroba]: but undef %hash and %hash = () both work, too, but the first one keeps the memory allocated, while the latter makes it available for other parts of the program.
[choroba]: iirc
[perldigious]: karlgoethebier: Well it is a pretty old and complicated (for me) bit of code I wrote (poorly by my current standards), so I'm expecting everything to break when I add the scoping and find out what else is undesireably scope changed. :-)
[perldigious]: Ah, thanks choroba, that sort of thing was precisely what I was wondering when I asked.
[perldigious]: I didn't want to tie up memory unecessarily basically, I wanted to "delete" it specifically to free it up, and wasn't sure I was even accomplishing that.

How do I use this? | Other CB clients
Other Users?
Others contemplating the Monastery: (5)
As of 2017-07-21 19:53 GMT
Find Nodes?
    Voting Booth?
    I came, I saw, I ...

    Results (335 votes). Check out past polls.