Beefy Boxes and Bandwidth Generously Provided by pair Networks
No such thing as a small change
 
PerlMonks  

Use reference for functions in functions

by Anonymous Monk
on Feb 25, 2013 at 19:16 UTC ( #1020553=perlquestion: print w/ replies, xml ) Need Help??
Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

Hello,

I would like some help with the following issue. I have code with creates a new object (object->new) and wish to use it a sub. This works fine with the passing of the object as reference. However, when I want to pass the object to another function, I fail to get the reference across correctly. What am I doing wrong?

main... $object->new; func1($object); func2($object); sub func1 (\$) { my $object=shift; $object->doSomething; } sub func2 (\$) { my $object=shift; $object->doSomethingElse; func1 ($object); }

Probably the call fo func1 in func2 has the variable added incorrectly, but I'm unable to find the solution for this. I can't believe this isn't possible in perl, so I must be at fault.

BTW awaiting the email for activating my account T_I I'm posting this anonymously.

Comment on Use reference for functions in functions
Download Code
Reaped: Duplicate:Please delete
by NodeReaper (Curate) on Feb 25, 2013 at 19:19 UTC
Re: Use reference for functions in functions
by BrowserUk (Pope) on Feb 25, 2013 at 19:20 UTC
    I have code with creates a new object (object->new) and wish to use it a sub.

    You haven't shown us what is inside your new() subroutine?

    This line: &object->new; looks very suspect.

    The normal idion is my $object = SomeClass->new;


    With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    "Science is about questioning the status quo. Questioning authority".
    In the absence of evidence, opinion is indistinguishable from prejudice.
Re: Use reference for functions in functions
by 7stud (Deacon) on Feb 25, 2013 at 19:39 UTC
    use strict; use warnings; use 5.012; package Dog; sub new { my $class = shift; my $self = {}; bless $self, $class; } sub bark { say 'woof'; } sub do_math { say '2 + 2 = 4'; } package main; sub func1 { my $obj = shift; $obj->do_math(); } sub func2 { my $obj = shift; $obj->bark(); func1($obj); } my $dog = Dog->new(); func2($dog); --output:-- woof 2 + 2 = 4
      Thanks,

      It's been years since I've did something with objects in Perl. (first and last time was in 2009) I forgot objects are already references. I'll test this at work and post the findings.

      Edit: Just tested the removal of \ in the prototyping and it works flawlessly. Thanks for the reminder that objects are already references..

        Do you know about Moose? Moose is the new OO paradigm in perl. See here and chromatic's Modern Perl book here.
Re: Use reference for functions in functions
by AnomalousMonk (Abbot) on Feb 25, 2013 at 23:42 UTC
    sub func1 (\$) { my $object=shift; $object->doSomething; }

    In addition to the problems pointed out by BrowserUk and 7stud, the code quoted above from the OP includes another practice you'll probably want to drop at the earliest opportunity: using prototypes. (See Far More than Everything You've Ever Wanted to Know about Prototypes in Perl -- by Tom Christiansen for a thorough discussion of many good reasons to avoid them unless you really know what they're doing.)

    The  (\$) prototype in the quoted code causes a reference to a scalar to be passed to the function as an argument. This scalar was an object reference to begin with, so what you wind up with is a reference-to-a-reference. This reference-to-a-reference must then be de-referenced in order to use it to invoke a class method. E.g.,
        ${$object}->doSomething;
    in the quoted code (assuming an otherwise-normal OO idiom). This is akin to putting your pants on over your head: it's a neat party trick, but probably not something you want to do every morning.

    >perl -wMstrict -le "package Dog; ;; use List::Util qw(sum); ;; sub new { my $class = shift; my $self = {}; bless $self, $class; } ;; sub bark { printf 'woof '; } ;; sub do_math { my $self = shift; $self->bark for 1 .. sum @_; } ;; ;; package main; ;; sub func1 (\$) { my $obj = shift; ${$obj}->bark(); print qq{\n}; } ;; sub func2 (\$;@) { my $obj = shift; ${$obj}->do_math(@_); print qq{\n}; } ;; my $dog = Dog->new(); func1($dog); func2($dog, 3, 2, 1); " woof woof woof woof woof woof woof

      Nice.

      In addition to the problems pointed out by BrowserUk and 7stud,

      Nope. You win.

      Problems with Reference Prototypes
      
      At some level, they're more predictable...But I'm afraid that these, too, may often be more trouble than they're worth.
      
      You see ... (\$) (\@) (\%) ... don't actually say that you must pass in a scalar reference, an array reference, and a hash reference. Rather, they say you must pass in a scalar variable, an array variable, and a hash variable. That means that the compiler insists upon seeing a properly notated variable of the given type, complete with ``$'', ``@'', or ``%'' in that slot ['slot' means the corresponding position in the argument list when you call the subroutine.] You must not use a backslash. The compiler silently supplies the backslash for you. 

      So given this sub:

      use strict; use warnings; use 5.012; sub do_stuff(\$) { my $sref = shift; say $$sref; }
      ...you can call the sub like this:
      my $str = 'hello'; do_stuff($str); #legal: no slash in position 1 of arg list --output:-- hello

      But the prototype prevents you from calling the sub like this:

      my $str = 'hello'; do_stuff(\$str); #illegal: slash in position 1 of arg list --output:-- Type of arg 1 to main::do_stuff must be scalar (not single ref constru +ctor)

      But the prototype doesn't stop you from doing this:

      my $str = \'hello'; do_stuff($str); #legal: no slash in position 1 of arg list --output:-- SCALAR(0x100839858)
      ...and then you end up with unintended consequences.

      Thanks for the pointer to the article. I'll read it and learn how to use prototyping correctly. I didn't choose IT as a profession just to skip everything I don't know how to do or use, but to learn new things. As of now, prototyping is going to be one of the latter.

      When doing something, it's worth doing it right.
      If it's not worth doing it right, it's not worth doing at all.

        The biggest thing to remember about prototypes is that you don't typically need them.

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://1020553]
Approved by Corion
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others romping around the Monastery: (17)
As of 2014-09-30 14:22 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    How do you remember the number of days in each month?











    Results (372 votes), past polls