Re: using shift and $_ in loop
by Corion (Patriarch) on Oct 21, 2009 at 15:30 UTC
|
I'm not sure that what you want to do is sane, but that might be because I don't know your purpose. The following works but leaves @_ unmodified until after your loop:
sub scribble {
for (@_) {
...
};
@_ = ();
};
Alternatively, with the assignment:
sub scribble {
while ($_ = shift) {
...
};
};
My second approach and your while(...) approach suffer from the same problem that they will end the loop if a false value is contained in @_ | [reply] [d/l] [select] |
|
|
Yes they do suffer that- it tests for truth.
Maybe I was too vague in my posting, if so I apologize.
I expect my sub to take an unforeseen number of arguments.
My sub will take the arguments, discard some, and the ones that are not discarded, will be altered- and a list of the altered arguments are returned back.
An example..
use Lingua::Names 'is_name';
my @a = qw/andy lo1 beca cris/;
my @A = alter(@a);
sub alter {
my @newlist;
for ( @_ ){
my $name = is_name($_) or next;
push @newlist, uc($name);
}
@newlist;
}
Now, how can I make this so I can use shift, maybe even a for loop with undef and last??? What might be apropriate here to make it a little more minimal?
This is a little closer..
sub alter {
my @newlist;
while ( @_ ){
$_ = shift @_;
my $name = is_name($_) or next;
push @newlist, uc($name);
}
@newlist;
}
I'm wondering if I can just shift and push from @_ and then return the modified @_ .. using $_ ??? Maybe this is just too much coffee speaking and I need to chill out?
| [reply] [d/l] [select] |
|
|
sub alter {
grep $_, map { uc is_name($_) } @_;
}
instead.
In Perl 6 I'd maybe write something more similar to what you wrote:
sub alter(*@a) {
gather for @a {
my $name = is_name($_);
take uc $name if $name;
}
}
Or even
sub alter(*@a) {
gather for @a.map({ is_name($_)}) {
take .uc if $_;
}
}
Perl 6 - links to (nearly) everything that is Perl 6.
| [reply] [d/l] [select] |
|
|
|
|
|
|
|
|
|
sub alter {
return
map uc,
grep is_name($_),
@_;
}
| [reply] [d/l] [select] |
|
|
If I'm reading this correctly, you want @A as the elements of @a that pass the is_name(x) test?
@A = grep { is_name($_) } @a;
perldoc -f grep is your friend.
Update: I just noticed the uc() you used. In that case:
@A = map { uc($_) } grep { is_name($_) } @a;
perldoc -f map is also your friend. | [reply] [d/l] [select] |
|
|
|
|
|
Re: using shift and $_ in loop
by ikegami (Patriarch) on Oct 21, 2009 at 15:45 UTC
|
You never assigned to $_. The equivalent of
sub scribble {
while ( $a = shift ){
$a; # has arg
}
}
that assigns to $_ is
sub scribble {
while ( $_ = shift ){
$_; # has arg
}
}
In both cases, you are using global variables. $_ is particularly dangerous to clobber. Fix:
sub scribble {
local $_;
while ( $_ = shift ){
$_; # has arg
}
}
| [reply] [d/l] [select] |
|
|
Thank you, this is really useful.
So, you suggest localizing $_ as a precaution?
| [reply] |
|
|
Yeah, don't clobber your caller's variables.
| [reply] |
|
|
|
|
Re: using shift and $_ in loop
by moritz (Cardinal) on Oct 21, 2009 at 15:27 UTC
|
If deconstruction of the @_ array is not required, just use
for (@_) {
print; # using $_ here
}
See shift, @_.
Perl 6 - links to (nearly) everything that is Perl 6.
| [reply] [d/l] [select] |
A reply falls below the community's threshold of quality. You may see it by logging in. |
Re: using shift and $_ in loop
by jakobi (Pilgrim) on Oct 21, 2009 at 16:08 UTC
|
Leocharre, you're right on in being cautious of the truth of the loop condition. Which is necessary due to the lack of while(<>)-style magic in a mere while($_=shift){}.
Consider how the usual looping variants work or mostly fail, or just ask Perl with a simple, cute and short one-liner:
perl -e 'use Data::Dumper; @a=(1,0,undef,2); print Dumper(@a); print "
+1=$_=\n" foreach (@a); @ARGV=@a; print "2=$_=\n" while($_=shift @a);
+@a=@ARGV; print "3=$_=\n" while($_=shift @a,defined $_); @a=@ARGV; pr
+int "4=$_=\n" while($_=shift);'
PS: ad local: local($_) helps to not hurt the caller (but isn't e.g. necessary in a foreach(@a) scope), while my($_) (since 5.10) helps the current scope to not be hurt by called routines (and signal handlers, etc).
\Peter, who is wondering whether the line-eater did like the taste of his attempted .sig | [reply] [d/l] [select] |
Re: using shift and $_ in loop
by johngg (Canon) on Oct 21, 2009 at 16:59 UTC
|
$ perl -le '
> sub isname { return 1 if $_[ 0 ] =~ m{(?i)^(?:bill|fred)$} }
> @a = qw{ apple peach fred };
> sub alter
> {
> my @new =
> map { uc }
> grep { isname( $_ ) }
> map { my $w = shift }
> 0 .. $#_;
> }
> @A = alter( @a );
> print for @A;'
FRED
$
I hope this is of interest.
| [reply] [d/l] |
Re: using shift and $_ in loop
by pileofrogs (Priest) on Oct 21, 2009 at 19:47 UTC
|
( And I mean, seriously... where the #$!@& is shift output going?? Is its scope only in () ??? )
Actually, it's scope is the whole while loop. For instance..
for my $foo (@wibble) {
print $foo;
}
Oh, and $_ is global, as mentioned above (said Pileofrog as though he already knew that...) so the scope won't matter.
UpdateD'oh! Removed stupid '=' sign. Thanks moritz. | [reply] [d/l] |
|
|
... so the scope won't matter.
Famous last words :-)
| [reply] |