Re: modify variable on pass by value
by merlyn (Sage) on Sep 11, 2000 at 20:23 UTC
|
If you pass an lvalue to a subroutine, then assigning to the corresponding element
of @_ will alter the lvalue, as in:
sub remove_caps {
$_[0] =~ tr/A-Z//d;
}
But now that you've asked for this, and I've answered it, let me give you some
advice. Don't write subroutines like this. Perl works much better
in a flow model, not a do-this-to-that model. For example, early versions
of HTML::Entities::encode_entities worked that way, and after Gisle
found enough places where it was a real bear to use, he changed it to be a
return-value operator (with a backwards-compatibility mode).
So, save yourself the trouble. Use the return value. Don't alter the arguments.
-- Randal L. Schwartz, Perl hacker | [reply] [Watch: Dir/Any] [d/l] |
|
| [reply] [Watch: Dir/Any] |
|
I'm not talking about efficiency. I'm talking about natural flow in programming.
Every time I have to stop to use a foreach loop because a map wouldn't work,
I have to create temporary variables, think of reasonable names for them,
and then document them, and ensure their scope is large enough but not too large.
Don't get me wrong. I'm not an FP fascist. But most of the time, temporary values
forced on me by the syntax just seems awkward.
Let's go back to this remove-cap function. In a return-value situation, I can use
it like this:
my @data = map { RemoveCaps $_ } @input;
Whereas in a act-on-arguments mode, I've got to write this:
my @data = map { my $x = $_; RemoveCaps $x; $x } @input;
I can't use $_ directly, because it would attempt to alter @input
(see the other thread on that {grin}). So now I have to invent a stand-in,
just so I can act on it.
Just one guy's opinion from someone who's been coding for 30+ years.
-- Randal L. Schwartz, Perl hacker | [reply] [Watch: Dir/Any] [d/l] [select] |
|
|
|
|
|
RE: modify variable on pass by value
by cianoz (Friar) on Sep 11, 2000 at 20:31 UTC
|
#!/usr/bin/perl -w
sub remove_caps(\$) {
## ^^^ here's the magic...
my $val = shift;
$$val =~ s/[A-Z]+//g;
#this removes _all_ caps...
}
my $test = 'Hello World';
remove_caps($test);
print "$test\n";
| [reply] [Watch: Dir/Any] [d/l] |
(jcwren) RE: modify variable on pass by value
by jcwren (Prior) on Sep 11, 2000 at 20:57 UTC
|
merlyn may want to use a map() function, but a *really* good function handles scalars or arrays as inputs. To that end, here is an example that runs all the test cases I could think of.
#!/usr/local/bin/perl -w
use strict;
{
test1 ();
test2 ();
test3 ();
test4 ();
}
#
# Uses a simple scalar
#
sub test1
{
my $i = "Hello, World";
print "return - '", remove_caps ($i), "', \$i ='$i'\n";
}
#
# Simple scalar, result is set to a different variable
#
sub test2
{
my $i = "Hello, World";
my $o = remove_caps ($i);
print "return - \$i='$i', \$o='$o'\n";
}
#
# Pass a constant
#
sub test3
{
print "constant - ", remove_caps ("Hello, World"), "\n";
}
#
# Operate on an array
#
sub test4
{
my @iarray = ('Hello, World', 'Goodbye, Cruel World', 'Britney Spea
+rs Sux');
my @oarray = remove_caps (@iarray);
print "iarray = "; print "'$_', " foreach (@iarray); print "\n";
print "oarray = "; print "'$_', " foreach (@oarray); print "\n";
}
#
# Our humble little function
#
sub remove_caps
{
my @out = @_;
tr/A-Z//d for (@out);
return wantarray ? @out : $out[0];
}
--Chris
e-mail jcwren | [reply] [Watch: Dir/Any] [d/l] |
|
sub remove_caps;
if (1 != @_) {
return map {remove_caps($_)} @_;
}
my $str = shift;
$str =~ tr/A-Z//d;
return $str;
}
| [reply] [Watch: Dir/Any] [d/l] |
RE: modify variable on pass by value
by little (Curate) on Sep 11, 2000 at 21:00 UTC
|
#!/usr/local/bin/perl
my $string = 'Hello, World ,,, my World 1984';
$string =~ s/\b\w//g;
print $string;
there are my two cents | [reply] [Watch: Dir/Any] [d/l] |
|
Just thought I'd post that this code actually strips the first letter/number of each "word" (but not the first comma) rather than just the capital letters (also stripped the newlines I added to the end of the string as well). Sadly, I do not have much knowledge in the way of regexps, so I can't add any insight into making this do exactly what the poster wanted, but the code from cianoz above worked great.
| [reply] [Watch: Dir/Any] |
|
so, you'd suggest we end up with a version near to merlyns
proposal
=~ s/\b([A-Z])//g;
but chop doesn't care if it's a number and would even remove escape charcters completly if at the end of that string. | [reply] [Watch: Dir/Any] [d/l] |
RE: modify variable on pass by value
by reisu (Initiate) on Sep 12, 2000 at 00:14 UTC
|
Well, it's not a function, but it works...
my $string = "Hello World";
print "\L$string\E";
Sorry if I've missed the point here, just tossing my two robes in:) | [reply] [Watch: Dir/Any] [d/l] |
|
The point isn't to lowercase any uppercase letters, rather to remove them. Yours doesn't do this.
Cheers,
KM
| [reply] [Watch: Dir/Any] |
|
Ahhh! That'll learn me for writing without fully reading first...my bad:(
Sorry about that.
| [reply] [Watch: Dir/Any] |