Re: Shortcut operator for $a->{'b'}=$b if $b;
by merlyn (Sage) on Sep 20, 2005 at 16:33 UTC
|
$_ and $a->{b} = $_ for $b;
| [reply] [Watch: Dir/Any] [d/l] |
|
| [reply] [Watch: Dir/Any] [d/l] [select] |
|
I thought the point was that $b was standing in for something very complex or impossible to repeat for calculation.
| [reply] [Watch: Dir/Any] |
|
|
foreach loops sets $_ to refer to the current value in the list which is being iterated. In this case, the list consists solely of $b.
Your expression is equivalent, but it's not an acceptable answer since the question was about removing the need for using $b twice.
| [reply] [Watch: Dir/Any] |
Re: Shortcut operator for $a->{'b'}=$b if $b;
by Roy Johnson (Monsignor) on Sep 20, 2005 at 16:46 UTC
|
{ $a->{'b'} = do {$b or last} }
might abort the assignment if $b is not true. I can't test it at the moment. Another idea that occurs to me is
($a->{'b'} = $b) or delete $a->{'b'};
which expresses pretty directly what you said in your last sentence.
Caution: Contents may have been coded under pressure.
| [reply] [Watch: Dir/Any] [d/l] [select] |
|
I'd change the first one to simply:
{ $a->{b} = $b || last }
| [reply] [Watch: Dir/Any] [d/l] |
|
Tested. last does the trick.
| [reply] [Watch: Dir/Any] [d/l] |
|
It doesn’t “abort” the assignment – the logical OR is evaluated first, then possibly the last, and if that is evaluated, it prevents the assignment from evaluating at all. And thus it works.
Makeshifts last the longest.
| [reply] [Watch: Dir/Any] [d/l] |
|
And thereby logical false values do not get assigned, which is not as per the specs.
CountZero "If you have four groups working on a compiler, you'll get a 4-pass compiler." - Conway's Law
| [reply] [Watch: Dir/Any] |
|
Re: Shortcut operator for $a->{'b'}=$b if $b;
by ikegami (Patriarch) on Sep 20, 2005 at 16:24 UTC
|
I assume you mean $b is a long expression, so you'd rather avoid having it twice. If so, you could topicalize $b:
{
local $_ = $b;
$a->{b} = $_ if defined $_;
}
or (update)
$a->{b} = $_ foreach grep defined, $b;
or you could add everything then remove undefined values:
delete @$a{ grep { not defined $a->{$_} } keys %$a };
| [reply] [Watch: Dir/Any] [d/l] [select] |
|
Yes. If there's no shortcut operator, then your suggestion is the cleanest it'll get.
I was hoping there existed an "assign-if-true" operator.
| [reply] [Watch: Dir/Any] |
|
sub assign_if_defined {
$_[0] = $_[1] if defined $_[1];
}
assign_if_defined($a->{'b'}, $b);
By the way, I'm using defined since you said you didn't want empty keys. Checking for truthfullness (as you have been doing) removes both empty and false keys. Just remove the word defined for a truth test. | [reply] [Watch: Dir/Any] [d/l] [select] |
|
|
Re: Shortcut operator for $a->{'b'}=$b if $b;
by Codon (Friar) on Sep 20, 2005 at 16:35 UTC
|
What is the correlation between 'b' and $b? Is one used to derive the other? If so, then map may help.
$a = {
map {
$val = some_derivation($_)
? ( $_ => $val )
: ()
} qw(a b c)
};
Ivan Heffner
Sr. Software Engineer, DAS Lead
WhitePages.com, Inc.
| [reply] [Watch: Dir/Any] [d/l] [select] |
|
No correlation at all. This all started when I discovered the
||= operator, which test the assignee for truth, upon false assigns the assignor. I wanted to test the other side, and assign upon false.
I think my answer is no.
| [reply] [Watch: Dir/Any] |
|
"assigns the assignor"? Every definition I can find for "assignor" defines it as the person (or in the case operator) who does the assignment. In other words, "=" is the assignor, not "$b".
The standard terminology for assignments is "lvalue" for the variable receiving the value (which is usually on the *l*eft) and "rvalue" for the value being copied (which is usually on the *r*ight).
| [reply] [Watch: Dir/Any] |
Re: Shortcut operator for $a->{'b'}=$b if $b;
by polypompholyx (Chaplain) on Sep 20, 2005 at 17:24 UTC
|
It's slightly OT, but you probably want to avoid using $a and $b (even as metasyntax), as they are used in sort code blocks. As such, they are exempted from strict checking, and could introduce subtle bugs.
| [reply] [Watch: Dir/Any] [d/l] [select] |
Re: Shortcut operator for $a->{'b'}=$b if $b;
by halley (Prior) on Sep 20, 2005 at 16:26 UTC
|
No really swift code I can think of, which prevents the keys from being inserted. But if you can allow empty keys to exist briefly, you can audit them afterwards:
$a = { d=>1, e=>2, f=>3, g=>undef, h=>0, i=>4 };
delete @$a{ grep { not $a->{$_} } keys %$a };
Of course, that's just shifting the ugliness.
-- [ e d @ h a l l e y . c c ]
| [reply] [Watch: Dir/Any] [d/l] |
|
for (keys %$a) { delete $a->{$_} unless $a->{$_} }
Note: that should probably be unless defined $a->{$_} so we don't remove false keys, but I made the choice to mirror the OP's syntax.
<-radiant.matrix->
Larry Wall is Yoda: there is no try{} (ok, except in Perl6; way to ruin a joke, Larry! ;P)
The Code that can be seen is not the true Code
"In any sufficiently large group of people, most are idiots" - Kaa's Law
| [reply] [Watch: Dir/Any] [d/l] |
Re: Shortcut operator for $a->{'b'}=$b if $b;
by dragonchild (Archbishop) on Sep 21, 2005 at 03:41 UTC
|
No-one's mentioned using tie.
package Tie::Hash::OnlyIf;
sub STORE {
my $self = shift;
my ($key, $val) = @_;
if ( $val ) {
$self->{$key} = $val;
}
}
package main;
tie my %data, Tie::Hash::OnlyIf;
$data{b} = $b;
The only problem with this is that the casual reader will expect that the key 'b' will exist. But, it is a solution.
Oh - and tie's a lot slower than normal hashes, but performance is almost always overvalued. Going from 0.01 to 0.08 seconds per execution isn't noticeable.
My criteria for good software:
- Does it work?
- Can someone else come in, make a change, and be reasonably certain no bugs were introduced?
| [reply] [Watch: Dir/Any] [d/l] |
Re: Shortcut operator for $a->{'b'}=$b if $b;
by radiantmatrix (Parson) on Sep 20, 2005 at 17:43 UTC
|
You could abstract $b away into a sub (I'm assuming you're using it as a placeholder for a complex operation), and do something like:
sub b {
return $b;
}
b() and $a->{'b'} = b();
I guess I don't really understand where your "way too verbose" is coming from; it would help if I could see a more involved example of the code you're attempting to simplify.
<-radiant.matrix->
Larry Wall is Yoda: there is no try{} (ok, except in Perl6; way to ruin a joke, Larry! ;P)
The Code that can be seen is not the true Code
"In any sufficiently large group of people, most are idiots" - Kaa's Law
| [reply] [Watch: Dir/Any] [d/l] |
Re: Shortcut operator for $a->{'b'}=$b if $b;
by rir (Vicar) on Sep 21, 2005 at 04:03 UTC
|
{
$hash{data} = $_ if defined ( local $_ = $something );
}
A simple if-block is not to be faulted
but if you are going to use a single statement a large $something should come last; else it
will obscure following logic.
With the above it is easy to forget to close a scope over
the local.
Be well,
rir | [reply] [Watch: Dir/Any] [d/l] [select] |