Beefy Boxes and Bandwidth Generously Provided by pair Networks
Problems? Is your data what you think it is?
 
PerlMonks  

pass by value vs reference and return by value

by ganeshPerlStarter (Novice)
on Oct 27, 2013 at 13:46 UTC ( [id://1059903]=perlquestion: print w/replies, xml ) Need Help??

ganeshPerlStarter has asked for the wisdom of the Perl Monks concerning the following question:

Dear Perl Monk friends, I am primarily a C++ programmer and now learning perl. This question is to know difference between pass by value vs reference to function in perl and C++. C++ recommends pass-by-reference to avoid object copying overhead, since pass-by-value involves copy of the object being passed to function. Also, when we return an object (return-by-value) from a C++ function, it involves a temp object creation & destruction. perl also allows pass-by-reference to functions. Also, we can return values or references from perl functions. In this context, does pass-by-reference and return-by-reference help to avoid object copying overhead in perl also? I am trying to optimize my perl script so that when there are many functions, I want to reduce/eliminate the overhead of object copying while passing them to and returning from functions. I've a perl script which parses lot of data from web & it takes too long to process the data. That's why I am looking at these aspects in my script. Many thanks for clarifying my query. Best Regards ganesh
  • Comment on pass by value vs reference and return by value

Replies are listed 'Best First'.
Re: pass by value vs reference and return by value
by hippo (Bishop) on Oct 27, 2013 at 14:08 UTC

    Objects in Perl are references anyway, specifically blessed references. Therefore when you pass an object to a subroutine you are necessarily passing by reference. For example, in the following snippet $obj is passed by reference and may be altered by munge_it()

    my $obj = Some::Class->new (); munge_it ($obj, $data);

    No copying of objects should have occurred here.

    If you want to know why your script is slow, profile it. Much better than guessing and spending time "optimising" some part of the script which doesn't require it.

    Good luck.

Re: pass by value vs reference and return by value
by Athanasius (Archbishop) on Oct 27, 2013 at 14:57 UTC

    In C and C++, the default mechanism for passing arguments to a function is pass-by-value. To get pass-by-reference, you need to (in effect) override the default by explicitly either (1) passing a pointer (simulated pass-by-reference) or (2) declaring the function parameter to be a reference (C++ only).

    In Perl, it’s the other way around. The default mechanism for passing arguments to a subroutine is pass-by-reference. For example, if you call:

    foo($x, $y, $z);

    then within the body of sub foo the special array variable @_ contains references to the three arguments. In Perl terminology, $_[0] is an alias for $x, $_[1] is an alias for $y, and $_[2] is an alias for $z. This is strictly equivalent to a reference in C++: any changes made to $_[0] within sub foo are actually made to $x. The normal Perl idiom is to simulate pass-by-value by beginning the function body like this:

    sub foo { my ($p, $q, $r) = @_; ... }

    which makes local copies of the subroutine arguments.

    Note that in Perl arguments are passed in to @_ as a flat list of scalar values. So if you want to pass in, say, two arrays, and retain their separate identities, you use references: foo(\@array1, \@array2); which are themselves scalars. These work like C pointers (or C++ references). As hippo has explained, Perl objects are also references, so when an object argument is copied within a subroutine, it is only the reference — and not the underlying object — which is copied.

    As regards return-by-reference, remember that Perl uses reference-counted garbage collection, so it is safe to create an object within a subroutine and then return it to the caller. And since objects are references, returning an object involves the copying of a single scalar value (the reference) only.

    See perlreftut and perlootut.

    Hope that helps,

    Athanasius <°(((><contra mundum Iustus alius egestas vitae, eros Piratica,

Re: pass by value vs reference and return by value (terms)
by tye (Sage) on Oct 27, 2013 at 16:46 UTC

    In C++ "reference" means a pointer that is automatically dereferenced (so the syntax of using it is the same as the syntax for a non-pointer but the underlying mechanics are the same as a pointer). In Perl, "reference" just means "pointer" (there are, of course, differences between a Perl reference and a C++ pointer, but they are trivial differences compared to those between a Perl reference and a C++ reference).

    In Perl, even at the point where you declare/create an object, you are dealing with a Perl reference (a pointer). So passing in or returning an object in Perl never involves copying the object (just copying the pointer). So your concerns simply don't apply to Perl objects.

    So the answer to your question is: It doesn't matter. You already aren't making copies of objects so stop worrying about that. But I'd like to address a few more confusing points.

    So, given that "reference" means something quite different in Perl, people who say that Perl does "pass by reference" are incorrect. What Perl does (always, not "by default") is "pass by alias". If you directly access individual members of @_, then you are accessing the actual variables given as arguments to the function (for each argument that was simply a variable, not some expression). This is similar to what other languages call "pass by reference".

    The best and common practice is to copy the aliases from @_ into named lexical variables at the very top of the function so that the effect is "pass by value". The copying can be seen explicitly in the code; it isn't some option with how you declare the function.

    But, of course, with Perl objects, copying the lexical value is just copying the reference (a pointer), so both copies still point to the same object. So changes made through one copy will be seen by the other copy. If you want a function to make changes to a copy of an object and not have those impact the original object, then you have to do the copying explicitly, probably by calling a method on the object. But there is no one standard method name for copying an object in Perl. Sometimes $object->new() does that. Other times the method is called "clone". Many classes have no copy method implemented.

    - tye        

Re: pass by value vs reference and return by value
by ww (Archbishop) on Oct 27, 2013 at 16:07 UTC

    As to return by value, an example:

    #!/usr/bin/perl use 5.016; use warnings; use Data::Dumper; # pass by ref; return by val my $foo = "abc"; sub subr { my $local_foo = shift; # see Note1, below my $local_deref = $$local_foo; say " In sub, \$local_deref: $local_deref"; $local_deref .= " def"; say "\t And now, after cat, \$local_deref: $local_deref"; return $local_deref; } my $fooref = \$foo; my $result = subr($fooref); say "\t\t Back in main, after subr has returned."; say "\t\t $result";

    Produces output:

    In sub, $local_deref: abc And now, after cat, $local_deref: abc def Back in main, after subr has returned. abc def

    Note1: Had you attempted to -- for example --  print "DEBUG: \$local_foo: $local_foo"; before the deref you would be advised:

     DEBUG: $local_foo: SCALAR(0x169ef64)
    ... where the hex value (address) will vary with machine, OS or, possibly, whether the butterfly's wings are flapping upward or downward in the jungles or Borneo.


    If you didn't program your executable by toggling in binary with a bat-handle switch, it wasn't really programming!

Re: pass by value vs reference and return by value
by Laurent_R (Canon) on Oct 27, 2013 at 17:16 UTC

    OK, you've got the picture by now, you are unlikely to solve your slowness issue by changing the way you pass arguments around. But I can think of a number of things that a C or C++ programmer could do wrong in terms of speed and performance in Perl. Maybe you should post parts of your code so that you might get advice on how to do certain things better.

    The one thing you should probably do is to profile your code. There are a number of profiling modules available under the Devel:: name space of the CPAN, such as the simple Devel::Profile module or the much more feature-rich Devel::NYTProf module, etc.

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others chanting in the Monastery: (8)
As of 2024-04-19 08:45 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found