reference to object method

Discussion in 'Perl Misc' started by Hobo Salesman, Jun 15, 2006.

  1. Can I store a reference to an object method in a scalar and use that to
    call the method? Something like (and I'm sure this is wrong):

    $methodRef = \$object->method();
    &{$methodRef}($argument);
    Hobo Salesman, Jun 15, 2006
    #1
    1. Advertising

  2. Hobo Salesman

    Guest

    "Hobo Salesman" <> wrote:
    > Can I store a reference to an object method in a scalar and use that to
    > call the method? Something like (and I'm sure this is wrong):
    >
    > $methodRef = \$object->method();
    > &{$methodRef}($argument);



    my $ref = sub { $object->method(@_) };

    $ref->($argument);

    Xho

    --
    -------------------- http://NewsReader.Com/ --------------------
    Usenet Newsgroup Service $9.95/Month 30GB
    , Jun 15, 2006
    #2
    1. Advertising

  3. Hobo Salesman

    Uri Guttman Guest

    >>>>> "x" == xhoster <> writes:

    x> "Hobo Salesman" <> wrote:
    >> Can I store a reference to an object method in a scalar and use that to
    >> call the method? Something like (and I'm sure this is wrong):
    >>
    >> $methodRef = \$object->method();
    >> &{$methodRef}($argument);



    x> my $ref = sub { $object->method(@_) };

    x> $ref->($argument);

    much better to use UNIVERSAL::can:

    my $meth = $obj->can( 'method_name' ) ;

    $meth->( $arg ) ;

    uri

    --
    Uri Guttman ------ -------- http://www.stemsystems.com
    --Perl Consulting, Stem Development, Systems Architecture, Design and Coding-
    Search or Offer Perl Jobs ---------------------------- http://jobs.perl.org
    Uri Guttman, Jun 15, 2006
    #3
  4. Hobo Salesman

    Ben Morrow Guest

    Quoth Uri Guttman <>:
    > >>>>> "x" == xhoster <> writes:

    >
    > x> "Hobo Salesman" <> wrote:
    > >> Can I store a reference to an object method in a scalar and use that to
    > >> call the method? Something like (and I'm sure this is wrong):
    > >>
    > >> $methodRef = \$object->method();
    > >> &{$methodRef}($argument);

    >
    > x> my $ref = sub { $object->method(@_) };


    Note that $object must be a lexical here, or the anon sub won't close
    over it. (But it was anyway, of course... :) )

    > x> $ref->($argument);
    >
    > much better to use UNIVERSAL::can:
    >
    > my $meth = $obj->can( 'method_name' ) ;
    >
    > $meth->( $arg ) ;


    ....except that just calls the method as a sub, i.e. the invocant is not
    preserved. For that you need another closure, hence Xho's answer is the
    simplest possible.

    Ben

    --
    I touch the fire and it freezes me, []
    I look into it and it's black.
    Why can't I feel? My skin should crack and peel---
    I want the fire back... Buffy, 'Once More With Feeling'
    Ben Morrow, Jun 15, 2006
    #4
  5. Uri Guttman wrote:
    > xhoster <> writes:
    >> "Hobo Salesman" <> wrote:
    >>> Can I store a reference to an object method in a scalar and use that to
    >>> call the method?

    >>
    >> my $ref = sub { $object->method(@_) };
    >>
    >> $ref->($argument);

    >
    > much better to use UNIVERSAL::can:

    ^^^^^^^^^^^

    > my $meth = $obj->can( 'method_name' ) ;
    >
    > $meth->( $arg ) ;


    Why?

    --
    Gunnar Hjalmarsson
    Email: http://www.gunnar.cc/cgi-bin/contact.pl
    Gunnar Hjalmarsson, Jun 15, 2006
    #5
  6. Hobo Salesman

    Anno Siegel Guest

    Uri Guttman wrote:

    >>>>>> "x" == xhoster <> writes:

    >
    > x> "Hobo Salesman" <> wrote:
    > >> Can I store a reference to an object method in a scalar and use that
    > >> to call the method? Something like (and I'm sure this is wrong):
    > >>
    > >> $methodRef = \$object->method();
    > >> &{$methodRef}($argument);

    >
    >
    > x> my $ref = sub { $object->method(@_) };
    >
    > x> $ref->($argument);
    >
    > much better to use UNIVERSAL::can:
    >
    > my $meth = $obj->can( 'method_name' ) ;
    >
    > $meth->( $arg ) ;


    Ah, but these are not the same. The way I read the OP, the idea is to
    freeze both the object and the method in a scalar, and that's what Xhos
    solution does. Yours only catches the method, the object would still
    have to be supplied as an argument.

    Anno
    Anno Siegel, Jun 15, 2006
    #6
  7. Hobo Salesman

    Uri Guttman Guest

    >>>>> "GH" == Gunnar Hjalmarsson <> writes:

    GH> Uri Guttman wrote:
    >> xhoster <> writes:
    >>> "Hobo Salesman" <> wrote:
    >>>> Can I store a reference to an object method in a scalar and use that to
    >>>> call the method?
    >>> my $ref = sub { $object->method(@_) };
    >>> $ref->($argument);

    >> much better to use UNIVERSAL::can:

    GH> ^^^^^^^^^^^

    >> my $meth = $obj->can( 'method_name' ) ;
    >> $meth->( $arg ) ;


    GH> Why?

    you don't need the extra complexity of a closure. why do something that
    is not needed?

    uri

    --
    Uri Guttman ------ -------- http://www.stemsystems.com
    --Perl Consulting, Stem Development, Systems Architecture, Design and Coding-
    Search or Offer Perl Jobs ---------------------------- http://jobs.perl.org
    Uri Guttman, Jun 15, 2006
    #7
  8. Hobo Salesman

    Uri Guttman Guest

    >>>>> "AS" == Anno Siegel <-berlin.de> writes:

    AS> Uri Guttman wrote:
    >>>>>>> "x" == xhoster <> writes:

    >>

    x> "Hobo Salesman" <> wrote:
    >> >> Can I store a reference to an object method in a scalar and use that
    >> >> to call the method? Something like (and I'm sure this is wrong):
    >> >>
    >> >> $methodRef = \$object->method();
    >> >> &{$methodRef}($argument);

    >>
    >>

    x> my $ref = sub { $object->method(@_) };
    >>

    x> $ref->($argument);
    >>
    >> much better to use UNIVERSAL::can:
    >>
    >> my $meth = $obj->can( 'method_name' ) ;
    >>
    >> $meth->( $arg ) ;


    AS> Ah, but these are not the same. The way I read the OP, the idea is to
    AS> freeze both the object and the method in a scalar, and that's what Xhos
    AS> solution does. Yours only catches the method, the object would still
    AS> have to be supplied as an argument.

    i read it as i answered it. we can agree the OP is somewhat ambiguous
    there. i see reference to a method (found via an object). he seems to
    have the object floating around and so it doesn't need to be stored in
    the closure (and so the closure isn't needed). so the OP would need to
    clarify this.

    uri

    --
    Uri Guttman ------ -------- http://www.stemsystems.com
    --Perl Consulting, Stem Development, Systems Architecture, Design and Coding-
    Search or Offer Perl Jobs ---------------------------- http://jobs.perl.org
    Uri Guttman, Jun 15, 2006
    #8
  9. Hobo Salesman

    Guest

    Uri Guttman <> wrote:
    > >>>>> "x" == xhoster <> writes:

    >
    > x> "Hobo Salesman" <> wrote:
    > >> Can I store a reference to an object method in a scalar and use that
    > >> to call the method? Something like (and I'm sure this is wrong):
    > >>
    > >> $methodRef = \$object->method();
    > >> &{$methodRef}($argument);

    >
    > x> my $ref = sub { $object->method(@_) };
    >
    > x> $ref->($argument);
    >
    > much better to use UNIVERSAL::can:


    Neat, I've never considered can to return more than a boolean.

    > my $meth = $obj->can( 'method_name' ) ;
    >
    > $meth->( $arg ) ;


    Doesn't that call the method as a regular subroutine, with $arg where $self
    should be?

    Wouldn't that need to be: ?
    $obj->$meth($arg);

    The anonymous sub method stores the object as a closure (well, as long
    as it is a lexical, anyway), whereas the UNIVERSAL::can method requires you
    to keep your hands on the object your own self. I thought that the point
    of the OP was not to have to do that, but maybe I misread his point.


    Xho

    --
    -------------------- http://NewsReader.Com/ --------------------
    Usenet Newsgroup Service $9.95/Month 30GB
    , Jun 15, 2006
    #9
  10. Hobo Salesman wrote:
    > Can I store a reference to an object method in a scalar and use that to
    > call the method?


    Thanks for the solutions. I don't have a specific application, I'm just
    learning OOP and figuring out different ways to structure things.
    THanks again.
    Hobo Salesman, Jun 15, 2006
    #10
  11. Hobo Salesman

    Mumia W. Guest

    Hobo Salesman wrote:
    > Can I store a reference to an object method in a scalar and use that to
    > call the method? Something like (and I'm sure this is wrong):
    >
    > $methodRef = \$object->method();
    > &{$methodRef}($argument);
    >


    The others have given you good methods of doing this including their
    pros and cons. This method should avoid the need to lexicalize the
    object as well as store all the data required to do a proper method call:

    $callref = [ $obj->can('method') , $obj ];
    $callref->[0]($callref->[1]);

    You can make a sub to prettify the call site if you want to.

    sub cR {
    my ($sub, $obj, @arglist) = @_;
    $sub->($obj, @arglist);
    }

    cR @$callref;

    HTH
    Mumia W., Jun 15, 2006
    #11
  12. Hobo Salesman

    Ch Lamprecht Guest

    Uri Guttman wrote:
    >>>>>>"x" == xhoster <> writes:

    >
    >
    > x> Uri Guttman <> wrote:


    > >> much better to use UNIVERSAL::can:


    > >> my $meth = $obj->can( 'method_name' ) ;
    > >>
    > >> $meth->( $arg ) ;

    >
    > x> Doesn't that call the method as a regular subroutine, with $arg where $self
    > x> should be?
    >
    > x> Wouldn't that need to be: ?
    > x> $obj->$meth($arg);
    >
    > my bad. brain wasn't fully engaged. and i have used can like that a few
    > times so i should know how to call the method! your code is correct
    > there.


    It will still call the method as a regular subroutine...
    So maybe it should be better written as

    $meth->( $obj,$arg );

    Christoph


    --

    perl -e "print scalar reverse q//"
    Ch Lamprecht, Jun 15, 2006
    #12
  13. Hobo Salesman

    Uri Guttman Guest

    >>>>> "CL" == Ch Lamprecht <> writes:

    CL> Uri Guttman wrote:
    >>>>>>> "x" == xhoster <> writes:

    x> Uri Guttman <> wrote:

    >> >> much better to use UNIVERSAL::can:


    >> >> my $meth = $obj->can( 'method_name' ) ;
    >> >> >> $meth->( $arg ) ;

    x> Doesn't that call the method as a regular subroutine, with $arg
    >> where $self

    x> should be?
    x> Wouldn't that need to be: ?
    x> $obj->$meth($arg);
    >> my bad. brain wasn't fully engaged. and i have used can like that a
    >> few
    >> times so i should know how to call the method! your code is correct
    >> there.


    CL> It will still call the method as a regular subroutine...
    CL> So maybe it should be better written as

    CL> $meth->( $obj,$arg );

    no, xhoster's fix of my bug is correct. your way skips inheritance.

    $obj->$meth($arg);

    uri

    --
    Uri Guttman ------ -------- http://www.stemsystems.com
    --Perl Consulting, Stem Development, Systems Architecture, Design and Coding-
    Search or Offer Perl Jobs ---------------------------- http://jobs.perl.org
    Uri Guttman, Jun 15, 2006
    #13
  14. Hobo Salesman

    Ch Lamprecht Guest

    Uri Guttman wrote:
    >>>>>>"CL" == Ch Lamprecht <> writes:

    >
    >
    > CL> Uri Guttman wrote:
    > >>>>>>> "x" == xhoster <> writes:

    > x> Uri Guttman <> wrote:
    >
    > >> >> much better to use UNIVERSAL::can:

    >
    > >> >> my $meth = $obj->can( 'method_name' ) ;
    > >> >> >> $meth->( $arg ) ;

    > x> Doesn't that call the method as a regular subroutine, with $arg
    > >> where $self

    > x> should be?
    > x> Wouldn't that need to be: ?
    > x> $obj->$meth($arg);
    > >> my bad. brain wasn't fully engaged. and i have used can like that a
    > >> few
    > >> times so i should know how to call the method! your code is correct
    > >> there.

    >
    > CL> It will still call the method as a regular subroutine...
    > CL> So maybe it should be better written as
    >
    > CL> $meth->( $obj,$arg );
    >
    > no, xhoster's fix of my bug is correct. your way skips inheritance.
    >
    > $obj->$meth($arg);
    >
    > uri
    >

    so does his:

    #!/usr/bin/perl
    use strict;
    use warnings;

    package Object;

    sub new {
    my $self = {};
    bless $self;
    }

    sub method{
    my $self = shift;
    print "Object::method invoked on $self with args @_\n";
    }

    package DerivedObject;
    our @ISA = qw/Object/;
    sub new {
    my $self = {};
    bless $self;
    }

    sub method{
    my $self = shift;
    print "ObjectDerived::method invoked on $self with args @_\n";
    }

    package main;

    my $object = Object->new;
    my $object_derived = DerivedObject->new;

    my $method_ref = $object->can("method");
    my @args = qw/foo bar/;
    for ($object, $object_derived, 'nothing'){
    $method_ref->($_,@args);
    $_->$method_ref(@args);
    $_->method(@args);
    print "\n";
    }


    Christoph

    --

    perl -e "print scalar reverse q//"
    Ch Lamprecht, Jun 16, 2006
    #14
  15. Hobo Salesman

    Ben Morrow Guest

    Quoth Ch Lamprecht <>:
    > Uri Guttman wrote:
    > >>>>>>"CL" == Ch Lamprecht <> writes:

    > >
    > >
    > > CL> Uri Guttman wrote:
    > > >>>>>>> "x" == xhoster <> writes:

    > > x> Uri Guttman <> wrote:
    > >
    > > >> >> much better to use UNIVERSAL::can:

    > >
    > > >> >> my $meth = $obj->can( 'method_name' ) ;
    > > >> >> >> $meth->( $arg ) ;

    > > x> Doesn't that call the method as a regular subroutine, with $arg
    > > >> where $self

    > > x> should be?
    > > x> Wouldn't that need to be: ?
    > > x> $obj->$meth($arg);
    > > >> my bad. brain wasn't fully engaged. and i have used can like that a
    > > >> few
    > > >> times so i should know how to call the method! your code is correct
    > > >> there.

    > >
    > > CL> It will still call the method as a regular subroutine...
    > > CL> So maybe it should be better written as
    > >
    > > CL> $meth->( $obj,$arg );
    > >
    > > no, xhoster's fix of my bug is correct. your way skips inheritance.
    > >
    > > $obj->$meth($arg);
    > >

    > so does his:


    Err, yes... presumably that's the point of taking a ref to a method?

    Xho's fix is correct, your way is ugly :).

    Ben

    --
    #!/bin/sh
    quine="echo 'eval \$quine' >> \$0; echo quined"
    eval $quine
    # []
    Ben Morrow, Jun 16, 2006
    #15
  16. Hobo Salesman

    Ch Lamprecht Guest

    Ch Lamprecht wrote:
    > Uri Guttman wrote:
    >
    >>>>>>> "CL" == Ch Lamprecht <> writes:

    >>
    >>
    >>
    >> CL> Uri Guttman wrote:
    >> >>>>>>> "x" == xhoster <> writes:

    >> x> Uri Guttman <> wrote:
    >>
    >> >> >> much better to use UNIVERSAL::can:

    >>
    >> >> >> my $meth = $obj->can( 'method_name' ) ;
    >> >> >> >> $meth->( $arg ) ;

    >> x> Doesn't that call the method as a regular subroutine, with $arg
    >> >> where $self

    >> x> should be?
    >> x> Wouldn't that need to be: ?
    >> x> $obj->$meth($arg);
    >> >> my bad. brain wasn't fully engaged. and i have used can like that a
    >> >> few
    >> >> times so i should know how to call the method! your code is correct
    >> >> there.

    >>
    >> CL> It will still call the method as a regular subroutine...
    >> CL> So maybe it should be better written as
    >>
    >> CL> $meth->( $obj,$arg );
    >>
    >> no, xhoster's fix of my bug is correct. your way skips inheritance.
    >>
    >> $obj->$meth($arg);
    >>
    >> uri
    >>

    > so does his:


    Added the case you might be thinking of: ...??

    #!/usr/bin/perl
    use strict;
    use warnings;

    package Object;

    sub new {
    my $self = {};
    bless $self;
    }

    sub method{
    my $self = shift;
    print "Object::method invoked on $self with args @_\n";
    }

    package DerivedObject;
    our @ISA = qw/Object/;
    sub new {
    my $self = {};
    bless $self;
    }

    sub method{
    my $self = shift;
    print "ObjectDerived::method invoked on $self with args @_\n";
    }

    package main;

    my $object = Object->new;
    my $object_derived = DerivedObject->new;

    my $method_ref = $object->can('method');
    my $method_name = 'method';

    my @args = qw/foo bar/;
    for ($object, $object_derived, 'nothing'){
    $method_ref->($_,@args);
    $_->$method_ref(@args); # function call
    $_->$method_name(@args); # method call
    $_->method(@args);
    print "\n";
    }


    Christoph
    --

    perl -e "print scalar reverse q//"
    Ch Lamprecht, Jun 16, 2006
    #16
  17. Hobo Salesman

    Anno Siegel Guest

    Uri Guttman wrote:

    >>>>>> "CL" == Ch Lamprecht <> writes:

    >
    > CL> Uri Guttman wrote:
    > >>>>>>> "x" == xhoster <> writes:

    > x> Uri Guttman <> wrote:
    >
    > >> >> much better to use UNIVERSAL::can:

    >
    > >> >> my $meth = $obj->can( 'method_name' ) ;
    > >> >> >> $meth->( $arg ) ;

    > x> Doesn't that call the method as a regular subroutine, with $arg
    > >> where $self

    > x> should be?
    > x> Wouldn't that need to be: ?
    > x> $obj->$meth($arg);
    > >> my bad. brain wasn't fully engaged. and i have used can like that a
    > >> few
    > >> times so i should know how to call the method! your code is correct
    > >> there.

    >
    > CL> It will still call the method as a regular subroutine...
    > CL> So maybe it should be better written as
    >
    > CL> $meth->( $obj,$arg );
    >
    > no, xhoster's fix of my bug is correct. your way skips inheritance.
    >
    > $obj->$meth($arg);


    Same difference. Since $meth is a coderef inheritance doesn't enter
    the equation.

    Anno
    Anno Siegel, Jun 16, 2006
    #17
  18. Hobo Salesman

    Ch Lamprecht Guest

    Ben Morrow wrote:
    > Quoth Ch Lamprecht <>:
    >
    >>Uri Guttman wrote:
    >>
    >>>>>>>>"CL" == Ch Lamprecht <> writes:
    >>>
    >>>
    >>> CL> Uri Guttman wrote:
    >>> >>>>>>> "x" == xhoster <> writes:
    >>> x> Uri Guttman <> wrote:
    >>>
    >>> >> >> much better to use UNIVERSAL::can:
    >>>
    >>> >> >> my $meth = $obj->can( 'method_name' ) ;
    >>> >> >> >> $meth->( $arg ) ;
    >>> x> Doesn't that call the method as a regular subroutine, with $arg
    >>> >> where $self
    >>> x> should be?
    >>> x> Wouldn't that need to be: ?
    >>> x> $obj->$meth($arg);
    >>> >> my bad. brain wasn't fully engaged. and i have used can like that a
    >>> >> few
    >>> >> times so i should know how to call the method! your code is correct
    >>> >> there.
    >>>
    >>> CL> It will still call the method as a regular subroutine...
    >>> CL> So maybe it should be better written as
    >>>
    >>> CL> $meth->( $obj,$arg );
    >>>
    >>>no, xhoster's fix of my bug is correct. your way skips inheritance.
    >>>
    >>> $obj->$meth($arg);
    >>>

    >>
    >>so does his:

    >
    >
    > Err, yes... presumably that's the point of taking a ref to a method?
    >
    > Xho's fix is correct, your way is ugly :).


    Just in case you are missing my point:

    my $meth = $obj->can( 'method_name' ) ;

    $meth wil now contain a coderef if 'method_name' was found.
    According to perlref it would be called like:
    &{$meth}($obj,$arg);
    &$meth($obj,$arg);
    $meth->($obj,$arg);

    If you prefer to call it like so
    $obj->$meth($arg);
    I consider it to be misleading, because it looks like a method call without
    being one. Someone reading that line might think, $meth contained a method-name...

    Christoph




    --

    perl -e "print scalar reverse q//"
    Ch Lamprecht, Jun 16, 2006
    #18
  19. Hobo Salesman

    Uri Guttman Guest

    >>>>> "BM" == Ben Morrow <> writes:

    BM> Quoth Ch Lamprecht <>:
    >> Uri Guttman wrote:
    >> >>>>>>"CL" == Ch Lamprecht <> writes:
    >> >
    >> >
    >> > CL> Uri Guttman wrote:
    >> > >>>>>>> "x" == xhoster <> writes:
    >> > x> Uri Guttman <> wrote:
    >> >
    >> > >> >> much better to use UNIVERSAL::can:
    >> >
    >> > >> >> my $meth = $obj->can( 'method_name' ) ;
    >> > >> >> >> $meth->( $arg ) ;
    >> > x> Doesn't that call the method as a regular subroutine, with $arg
    >> > >> where $self
    >> > x> should be?
    >> > x> Wouldn't that need to be: ?
    >> > x> $obj->$meth($arg);
    >> > >> my bad. brain wasn't fully engaged. and i have used can like that a
    >> > >> few
    >> > >> times so i should know how to call the method! your code is correct
    >> > >> there.
    >> >
    >> > CL> It will still call the method as a regular subroutine...
    >> > CL> So maybe it should be better written as
    >> >
    >> > CL> $meth->( $obj,$arg );
    >> >
    >> > no, xhoster's fix of my bug is correct. your way skips inheritance.
    >> >
    >> > $obj->$meth($arg);
    >> >

    >> so does his:


    BM> Err, yes... presumably that's the point of taking a ref to a method?

    yeah, the OP's original issue is long lost in my skull. and i bet he
    isn't reading this thread anymore!

    BM> Xho's fix is correct, your way is ugly :).

    and your mother is fixed and also ugly too! :)

    uri

    --
    Uri Guttman ------ -------- http://www.stemsystems.com
    --Perl Consulting, Stem Development, Systems Architecture, Design and Coding-
    Search or Offer Perl Jobs ---------------------------- http://jobs.perl.org
    Uri Guttman, Jun 16, 2006
    #19
  20. Hobo Salesman

    John Bokma Guest

    Uri Guttman <> wrote:

    > and your mother is fixed and also ugly too! :)


    Ah, is it time for the "Your mother ..." jokes?

    --
    John Bokma Freelance software developer
    &
    Experienced Perl programmer: http://castleamber.com/
    John Bokma, Jun 16, 2006
    #20
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. ce
    Replies:
    1
    Views:
    2,985
  2. Replies:
    1
    Views:
    477
    Mark Rae [MVP]
    Sep 20, 2007
  3. Arv
    Replies:
    15
    Views:
    920
    James Kanze
    Mar 7, 2008
  4. Eric Mahurin
    Replies:
    4
    Views:
    245
    David A. Black
    May 6, 2005
  5. Elf M. Sternberg
    Replies:
    15
    Views:
    269
    Matthias Reitinger
    Jul 29, 2009
Loading...

Share This Page