This reference stuff carried over, of course, from C. Both are useful in certain situations, you simply must recognize them. Really, the speed issue should be an afterthought. When you pass by reference, you are passing almost the original object to the function. You can use this variable as if it had been called from the encapsulating function. When you return, the variable will remain what you set it in the calling function since any alteration in the function will have effect on the original variable. When you pass by reference, you are actually passing the variable's pointer address in memory.
Now, when you pass by value, you are passing the actual variable's value when you called the function from the caller. This value is taken and a personal copy for that function and that function only is created. Any changes made to that copy do not affect any other variable in the system.
Now, to your issue. In C, some variables are actually smaller than passing a pointer (reference), so the passing by value was actually preferable over passing by reference! But in Perl, there are no data types- even strings are held in the same variable. A typical string (keeping it simple) will easily eat up more than 16 or 32 bits (a typical pointer size). While internally, the pass is made with a pointer, perl will create a dynamic memory copy at some point before it continues in your code. If you do not need another copy to work on, pass by reference. In C, there is no penalty for pointers (references). In Perl, the penalty can become substantial- especially if you are derefencing in a loop- especially in a main or very important loop! In all cases, you should
- consider whether you really need a function. Questions: Will i reuse this code again? Will I not be using it all too often (perhaps for a simple conversion only)? Do I need recursion?
- consider which variables that you need to pass. Questions: Is this variable relevant in the function context?
- choose pass ref or pass val. Questions: Will this variable remain constant throughout my function?(pass by val unnecessary) Do I need to take this variable and change it even in the encapsulating function? (reference required) Do I need my own copy of the variable for my own use without affecting other variables? (pass by val necessary unless you ref and then copy manually)
Lastly, comes the speed check. As others have mentioned, Perl dereferencing takes time, so a Benchmark would be a good way to fly. On the other hand, sometimes it's obvious or irrelevant. Is the function only called once or twice in the program? Then the testing really won't reveal any mind-boggling speed increase. If the function is mission-critical and you really need that speed increase, go for it. Anyway, if you're using Perl, you're really not writing any OpenGL routines, so you should be all set with whatever you choose. If the shoe fits, wear it. One help may be to make sure that the user always has something to see. That means piping data straight to the user as it comes up (or in buffers thereof). That way, even if your program isn't fast, it'll seem fast!
Q: Could a variable assignment bypass the perl dereference mechanism, as in:
my $var=$bar->foo(); #deref here
&var; #yet another deref?
? thanx.
| [reply] [d/l] |
It's not entirely clear what you're trying to do in your question, but you're a little confused about the syntax.
To be able to call &var, there has to be an entry in the `var' stash's subroutine knob. In other words, you'd need to do this:
local *var = sub { ... }
So whatever you're doing above, if you're expecting $bar->foo() to return a subroutine reference, just stick it on the right side of my code there.
And yes, by doing this, you eliminate the dereferecing step. However, see tilly's response to this node where I mention this technique for reasons why this isn't generally all that useful.
-dlc
| [reply] [d/l] [select] |
You have to ask yourself what is slower...passing the array/hash, or the extra deference everytime you assess it.
Typically, passing by reference is a win, but now always.
Remember:
$foo{'bob'};
is faster than:
$bar->{'bob'}; # Slower, extra dereference
So if you have a small array/hash, and dereference it alot, code it both ways, and see what Benchmark tells you. I'm betting the difference will be small enough, you should be optimizing for readability instead.
Also, remember using reference allows you to modify the
actual variable, where normally you will just modify a copy. This, and not performance, will usually determine which you should use.
| [reply] [d/l] [select] |
Also, remember using reference allows you to modify the actual variable, where normally you will just modify a copy.
I'm sure you understand what really happens in a sub, but your wording is a bit vague, so I'll clarify this for monks who might not be familiar with this issue.
You will only modify a copy of a variable passed to a sub if you copy the arguments to new variables. If you modify the @_ array directly, you modify the original variables. Run the following snippet to see what I mean:
#!/usr/bin/perl -w
use strict;
my $test = "Hi there!";
change($test);
print $test;
sub change {
$_[0] = "Hey, this is different!\n";
}
Cheers,
Ovid
Join the Perlmonks Setiathome Group or just go the the link and check out our stats. | [reply] [d/l] |
all in all this is the old dilemma "pass by value" vs. "pass by reference"
when you pass by reference you can alter the content of the original variable... (unless you make a copy inside the subroutine, but then where is the gain?)
| [reply] |
Actually, it's not quit that simple. Perl's standard
calling convention isn't pass by value. The values that you
get in @_ are aliases to the original variables,
so changing @_ will change the values outside the
subroutine, as this simple test demonstrates.
my $x = 1;
mult($x);
print "$x\n";
sub mult {
$_[0] *= 10;
}
--
<http://www.dave.org.uk>
"Perl makes the fun jobs fun
and the boring jobs bearable" - me
| [reply] [d/l] |
When sending strings off to be mangled, do you want to
keep the unmangled version? Send a copy, not a reference.
Bet on about 90-95% pass by reference but don't get into
the habit without thinking about it. It can BITE you when
you least expect it.
From the performance standpoint, really small lists
don't matter =) On big lists, the answer is obvious.
--
$you = new YOU;
honk() if $you->love(perl) | [reply] |