IN SEARCH OF ELEGANT CODE: Setting a hash value to a chomp'ed thing

D

David Filmer

I can do this:

chomp($ps = `which ps`); #chomp that system-call linefeed!
%hash = ('key' => $ps);

but what I really want to do is something like this:

%hash = ('key' => chomp `which ps`);

(one command, no intermeditate variable) but Perl hates my syntax (and
the several similar variants I've guessed at, playing with different
parenthesis groupings).

Does anyone know the proper syntax?

PS - I know this works:
chomp($hash{'key'} = `which ps`);
but that's not how I want to declare it for reasons that would bog
down my post. It ought to be possible to do the same thing with
%hash=(key=>value) syntax.
 
J

John W. Krahn

David said:
I can do this:

chomp($ps = `which ps`); #chomp that system-call linefeed!
%hash = ('key' => $ps);

but what I really want to do is something like this:

%hash = ('key' => chomp `which ps`);

(one command, no intermeditate variable) but Perl hates my syntax (and
the several similar variants I've guessed at, playing with different
parenthesis groupings).

Does anyone know the proper syntax?

PS - I know this works:
chomp($hash{'key'} = `which ps`);
but that's not how I want to declare it for reasons that would bog
down my post. It ought to be possible to do the same thing with
%hash=(key=>value) syntax.

Well this will work, if that's what you want.

%hash = ( key => grep [ chomp ], `which ps` );


John
 
R

Randal L. Schwartz

David> I can do this:
David> chomp($ps = `which ps`); #chomp that system-call linefeed!
David> %hash = ('key' => $ps);

David> but what I really want to do is something like this:

David> %hash = ('key' => chomp `which ps`);

I've used this in the past:

%hash = (key => `which ps` =~ /(.*)/);

A faster variation of that with a bit more typing and risk:

%hash = (key => substr(`which ps`, 0, -1));

And if you're really into chomp:

%hash = (key => do { chomp(my $x = `which ps`); $x });

print "Just another Perl hacker,";
 
D

David Filmer

Brian McCauley said:
John W. Krahn said:
Well this will work, if that's what you want.

%hash = ( key => grep [ chomp ], `which ps` );

Wow, that's a neat trick.

Agreed! I had no idea you could do something like that. Kewl. Thanks!
 
B

Bart Lateur

David said:
I can do this:

chomp($ps = `which ps`); #chomp that system-call linefeed!
%hash = ('key' => $ps);

but what I really want to do is something like this:

%hash = ('key' => chomp `which ps`);

chomp($hash{key} = `which ps`);
 
D

Dave Saville

John W. Krahn said:
Well this will work, if that's what you want.

%hash = ( key => grep [ chomp ], `which ps` );

Wow, that's a neat trick.

Undoubtably - but could someone explain it in english please?

Regards

Dave Saville

NB switch saville for nospam in address
 
T

Tassilo v. Parseval

Also sprach Dave Saville:
John W. Krahn said:
Well this will work, if that's what you want.

%hash = ( key => grep [ chomp ], `which ps` );

Wow, that's a neat trick.

Undoubtably - but could someone explain it in english please?

Normally you'd write it as

%hash = ( key => grep chomp, `which ps` );

grep() runs through the list (in this case `which ps` that happens to
only have one element) and applies the code given as first argument
(chomp). If this code snippet returns a true value for a particular list
element, this item is allowed to pass through. It's a filter
essentially.

Now, the return value of chomp() is the number of characters removed
from the end of the string. So it returns true for any string it was
able to shorten. Additionally, any changes done to $_ in the first
argument to grep will show up in the returned list. So it filters and
modifies its arguments in one go.

John used '[ chomp ]' instead of 'chomp'. '[ anything() ]' will always
have a true value when evaluated in boolean context. That way, it is
ensured that every element of the list is passed on regardless of
whether anything was chomped off the end or not. Consider the difference
between %hash1 und %hash2 in this example:

use Data::Dumper;

@b = @a = "test";
%hash1 = ( key => grep chomp, @a );
%hash2 = ( key => grep [ chomp ], @b );
print Dumper \%hash1;
print Dumper \%hash2;
__END__
$VAR1 = {
'key' => undef
};
$VAR1 = {
'key' => 'test'
};

Instead of '[ chomp ]' you could also write 'chomp || 1'. This makes
the forcing to a true value a little clearer.

Hmmh, amazing how much words I sometimes need to explain a single Perl
statement...

Tassilo
 
D

Dave Saville

grep() runs through the list (in this case `which ps` that happens to
only have one element) and applies the code given as first argument
(chomp). If this code snippet returns a true value for a particular list
element, this item is allowed to pass through. It's a filter
essentially.

Oh - I was not aware that grep could take anything other than a regex -
too used to "real" grep I guess :)

Thank you - I think :)


Regards

Dave Saville

NB switch saville for nospam in address
 
D

David Filmer

Bart Lateur said:
chomp($hash{key} = `which ps`);

Yes, thanks, Bart, but I already knew that worked (see the PS in my
original post). I have a reason for wanting to use the
%hash=(key=>value) syntax (rather than %hash{key}=value syntax).

Thanks especially to Tassilo and Randall for (again) showing me new
and wonderful ways to use (if not to abuse) Perl. And, thanks Dave
Saville, for asking Tassilo to further elaborate on his ingenious
answer; his further explanation proved most enlightening.
 
G

Greg

Yes, thanks, Bart, but I already knew that worked (see the PS in my
original post). I have a reason for wanting to use the
%hash=(key=>value) syntax (rather than %hash{key}=value syntax).

Thanks especially to Tassilo and Randall for (again) showing me new
and wonderful ways to use (if not to abuse) Perl. And, thanks Dave
Saville, for asking Tassilo to further elaborate on his ingenious
answer; his further explanation proved most enlightening.

Another way would be to use the comma operator, as

use strict;
use warnings;
use Data::Dumper;

my %h;
my $i = 0;

while(<DATA>){
$h{$i++} = (chomp($_), $_);
}

print Dumper(\%h);

__DATA__
one
two
three
four
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,731
Messages
2,569,432
Members
44,832
Latest member
GlennSmall

Latest Threads

Top