in reply to Re: RFC Bridge::Simple
in thread RFC Bridge::Simple

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

Replies are listed 'Best First'.
Re^3: RFC Bridge::Simple
by plobsing (Friar) on Mar 10, 2008 at 22:18 UTC
    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;