in reply to converting libraries into modules

You can also write your functions so they work either way.

Say you create your module and export the half() function as before, you can have your function look like this:

sub half { my $number; if (ref($_[0]) eq 'MyPackage') { my $self = shift(); $number = shift(); } else { $number = shift(); } return $number / 2; }
so that, if called via $m->half(), it works the first way, but if called just via half() it works the second way.


($_='kkvvttuu bbooppuuiiffss qqffssmm iibbddllffss')
=~y~b-v~a-z~s; print

Replies are listed 'Best First'.
Re^2: converting libraries into modules
by chromatic (Archbishop) on Mar 05, 2006 at 21:27 UTC

    Ugh, please don't do that. It's brittle to maintain, hard to document, confusing to explain, and I've never seen a case where it really simplifies things.

    If you really need to export a simple procedural interface, create an object and export curried functions that use the object to call the methods.

      chromatic,
      While I tend to agree that having single functions that works as a method and an exportable function is usually a bad idea, your solution seems a bit over the OP's head. Would you mind providing a code sample, point to an existing wheel, or link to some documentation that does a better job explaining.

      For what it is worth - I really like that Perl6 will distinguish between methods and subs as well as provide multi-method dispatch.

      Cheers - L~R

        It could be as simple as:

        use vars '@EXPORT'; @EXPORT = qw( list of methods to curry ); sub import { my $class = shift; my $curried_object = $class->new(); my $caller = caller(); for my $export ( @EXPORT ) { *{ $caller . "::$export" } = sub { $curried_object->$export( @ +_ ) }; } }
Re^2: converting libraries into modules
by Andre_br (Pilgrim) on Mar 05, 2006 at 18:16 UTC
    Great! Now I got it!
    Thanks a lot for the replies, dragonchild, Courage, rvosa and Cody Pendant (great tip of yours, cody, this calling-aware approach!).
    I´m so glad to have you guys around, fellow monks!
    Take care!
    André
      Just to document an adaptation on Cody's approach, that I´ve just tested with success:

      Instead of

      sub half { my $number; if (ref($_[0]) eq 'MyPackage') { my $self = shift(); $number = shift(); } else { $number = shift(); } return $number / 2; }
      We can make the adaptation of all perl4-ish functions possible just by adding a single line, on the top of each function's code:

      sub half { if (ref($_[0]) =~ /MyPackage/ ) { my $self = shift; } # as the former Perl4-like functions don´t need the $self object, this + line's role is to clean up the first element of the @_ array! And, s +o, make things ready for the shifts your code already is set to! my $number = shift; return $number / 2; }
      Detail: I call all my methods libraries MyPackage, Mypackage2 etc, so by testing with this regexp, I don't even have to worry to adapt this one-line according to the library I´m converting into module! Just adding it all over the subs, and finally enter the OO world!
Re^2: converting libraries into modules
by rvosa (Curate) on Mar 05, 2006 at 22:43 UTC
    I don't think this approach really simplifies things (now you have two interfaces to explain), but if you do it this way I'd suggest you don't hardcode the class name into its methods. I think I'd do:
    sub half { my $number; if (ref $_[0] eq __PACKAGE__) { my ( $self, $number ) = @_; } # uncuddles elses are faster! else { $number = $_[0]; } return $number / 2; }
    Or even:
    sub half { my $number; if (ref $_[0]) { my ( $self, $number ) = @_; } # uncuddles elses are faster! else { $number = $_[0]; } return $number / 2; }
    And then, if you're one of those suspenders + belt (just to be safe, you know) kind of people, you can always do looks_like_number $number and throw an exception (with baroque stack trace) on false.
      # uncuddles elses are faster!

      What? Is that really true? I thought it was just a style choice...


        No, really, have you tried it with Benchmark?