in reply to RFC Bridge::Simple

As peter hinted, you are storing 2 independent things in the same place. I would suggest you either store the object and method map in separate slots of an array or hash, or curry the object into the methods in the method map.

I prefer the latter because it makes the structure of the bridge object simpler.
sub curry_method { my ($obj, $meth) = @_; sub { $obj->$meth(@_) }; }

Replies are listed 'Best First'.
Re^2: RFC Bridge::Simple
by TGI (Parson) on Mar 10, 2008 at 19:55 UTC

    You make a very good point about separating the 'name spaces' for the object's attribute storage and the method map.

    Perhaps I am still half-asleep, but I think the curry method routine is wrong. I think you need to shift the object and method values off @_. Otherwise $meth will be called with args that look like: ($obj, $obj, $meth, ... ).

    sub _curry_method { my $object = shift; my $method = shift; return sub { $object->method(@_) }; }

    I wonder if it makes sense to do this. I believe you wind up with a new closure for each method called on every instance of your bridge class. When I'm more awake I need to research how Perl handles garbage collection of code refs, and test to see if there any differences in memory or speed for this approach versus an AUTOLOADED method call.

    Update:Yep, I was half asleep. plobsing's correct, the my ($o, $m) = @_; is fine. I blame it on Daylight Savings Time... I wasn't keeping the various meanings of @_ straight.


    TGI says moo

      You have to keep the name space of a bridge clear, so I would inline the curry_method function (alternatively, you could keep it in some other namespace). However, here's a simple case demonstrating that slurping @_ works:
      $ perl -MCGI -e 'sub curry_method{ my ($o, $m) = @_; sub { $o->$m(@_) } } $c = CGI->new; $p = curry_method($c, 'p'); print $p->("Hello World"), "\n"' <p>Hello World</p>
      You make a good point about having a closure for every method of every instance of the bridge class. Its a little extra space for a little extra simplicity. I prefer simplicity to speed/space in this case.

      The doubled $obj in @_ only occurs if you are calling the thing like a method twice. Once the object is curried, the method becomes a plain old function. I envisioned something like this (untested):
      package Bridge::Simple; use strict; use Carp; sub new { my ($class, $obj, $mapping) = @_; my $self = {}; @{$self}{keys %$mapping} = map { my $meth = $_; sub { $obj->$meth(@_) } } values %$mapping; bless $self, $class; } sub AUTOLOAD { my $self = shift; our $AUTOLOAD =~ s/.*:://; croak "no method $AUTOLOAD" unless exists $self->{$AUTOLOAD}; goto $self->{$AUTOLOAD}; } 1;