Re: Dynamic Hash value
by Corion (Patriarch) on Apr 21, 2010 at 07:44 UTC
|
You need to delay the evaluation. Perl calculates each expression as it runs it, so later changes will not change the values already computed:
#!perl -w
use strict;
my $ini=4;
my $last=2;
my %result=(
SAS1=>$ini-$last, # 2
SAS2=>$last-$ini, # -2
SAS3=>$ini-$last # 2
);
If you want to keep changing $ini and $last, you can do that in a subroutine:
#!perl -w
use strict;
use Data::Dumper;
sub get_SAS {
my ($ini,$last) = @_;
my %result=(
SAS1=>$ini-$last, # 2
SAS2=>$last-$ini, # -2
SAS3=>$ini-$last # 2
);
return %result
};
my %res42 = get_SAS(4,2);
print Dumper \%res42;
my %res105 = get_SAS(10,5);
print Dumper \%res105;
__END__
$VAR1 = {
'SAS3' => 2,
'SAS2' => -2,
'SAS1' => 2
};
$VAR1 = {
'SAS3' => 5,
'SAS2' => -5,
'SAS1' => 5
};
There are also other ways to delay the calculation, but I think this is the easiest approach. | [reply] [d/l] [select] |
Re: Dynamic Hash value
by BrowserUk (Patriarch) on Apr 21, 2010 at 07:54 UTC
|
#! perl -slw
use strict;
use Data::Dump qw[ pp ];
{
package Tie::Scalar::Dynamic;
sub TIESCALAR {
my( $class, $coderef ) = @_;
return bless $coderef, $class;
}
sub FETCH {
my $this = shift;
return $this->();
}
sub STORE {
die 'This tied variable is readonly';
}
}
my( $ini, $last ) = ( 4, 2 );
my %result = (
SAS1 => 0,
SAS2 => 0,
SAS3 => 0,
);
tie $result{ SAS1 }, 'Tie::Scalar::Dynamic', sub{ $ini - $last };
tie $result{ SAS2 }, 'Tie::Scalar::Dynamic', sub{ $last - $ini };
tie $result{ SAS3 }, 'Tie::Scalar::Dynamic', sub{ $ini - $last };
pp \%result;
( $ini, $last ) = ( 123, -456 );
pp \%result;
__END__
c:\test>835979.pl
{ SAS1 => 2, SAS2 => -2, SAS3 => 2 }
{ SAS1 => 579, SAS2 => -579, SAS3 => 579 }
Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
"Science is about questioning the status quo. Questioning authority".
In the absence of evidence, opinion is indistinguishable from prejudice.
| [reply] [d/l] |
Re: Dynamic Hash value
by almut (Canon) on Apr 21, 2010 at 08:01 UTC
|
Another version, using a tied hash:
#!/usr/bin/perl
package DynHash;
use Tie::Hash;
our @ISA = 'Tie::StdHash';
sub TIEHASH {
my $class = shift;
return bless {}, $class;
}
sub FETCH {
my $self = shift;
return ${ $self->{$_[0]}[0] } - ${ $self->{$_[0]}[1] }
}
package main;
use Data::Dumper;
tie my %result, "DynHash";
my $ini = 4;
my $last = 2;
%result = (
SAS1 => [ \$ini, \$last ],
SAS2 => [ \$last, \$ini ],
SAS3 => [ \$ini, \$last ]
);
print Dumper \%result;
$ini = 10;
$last = 5;
print Dumper \%result;
__END__
$VAR1 = {
'SAS3' => 2,
'SAS2' => -2,
'SAS1' => 2
};
$VAR1 = {
'SAS3' => 5,
'SAS2' => -5,
'SAS1' => 5
};
i.e., store references to $ini and $last in the hash, and dynamically recompute the difference from them at the time the values of the (tied) hash are being fetched. | [reply] [d/l] [select] |
Re: Dynamic Hash value
by GrandFather (Saint) on Apr 21, 2010 at 08:04 UTC
|
Why?
Although there are ways to achieve the effect you describe (as others have indicated), it is likely that what you want to do can best be approached in a different way. Corion's sub get_SAS is a good example of how a very slight rethink of the problem may yeld a better solution, but we can't help you best (except by guessing and getting lucky) unless you supply the bigger picture.
Given that you show the result of printing the values contained in the hash it may be that you don't need a hash at all, but that an array may be more appropriate. How can we tell?
True laziness is hard work
| [reply] [d/l] |
|
Actually Like SAS1, SAS2, SAS3, ...etc are there. Based on those value i am calculating the value say $some_value.
which($some_value) may either $ini-$last or $last-$ini
So for that i am building hash %result with SAS1, SAS2., SAS.. as key and either $ini-$last or $last-$ini as value
So later in the code if i change the values of either $ini or $last then this changed value should reflect in the hash such that whenever i retrieved hash value using SASx as key then it should give the latest result .
If You wants to suggest something like Tie:Scalar please bit elaborate on Tie:Scalar thing as i dont know about that
Because somebody has suggested that. But i didn't get that. I found Corion's example is good actually
Please help me
Thanks
| [reply] |
|
my $last = 0;
my $ini = 0;
...
$last = <something else>;
...
$ini = <something else>;
... # now you need $some_value:
my $selector = 'SAS1';
my $some_value = compute_sas($selector, $ini, $last);
sub compute_sas {
my($selector, $ini, $last) = @_;
if($selector eq 'SAS1') {
return $ini - $last;
} else {
return $last - $ini;
}
}
Note that the sub compute_sas is sloppy, untested and probably not giving the right results, but it should illustrate my point.
| [reply] [d/l] [select] |
|
> If You wants to suggest something like Tie:Scalar please bit elaborate on Tie:Scalar thing as i dont know about that
Because somebody has suggested that. But i didn't get that.
I suggested others already "elaborated", but it seems you didn't read ...
Paṛha kr̥payā!
> I found Corion's example is good actually
>
> Please help me
My helpful advice: Use Corions example!
> Thanks
Your welcome! 8)
| [reply] |
Re: Dynamic Hash value
by rovf (Priest) on Apr 21, 2010 at 07:49 UTC
|
| [reply] [d/l] |
Re: Dynamic Hash value
by LanX (Saint) on Apr 21, 2010 at 08:42 UTC
|
$\="\n";$,="\t";
{
package SAS;
our ($ini,$last);
sub _1 {$ini-$last}
sub _2{$last-$ini}
sub _3 {$ini-$last}
}
$SAS::ini=4;
$SAS::last=2;
print &SAS::_1, &SAS::_2 , &SAS::_3;
#or
package SAS2;
our ($ini,$last);
sub _1 {$ini-$last}
sub _2{$last-$ini}
sub _3 {$ini-$last}
package main;
$ini=10;
$last=5;
print SAS2::_1(), SAS2::_2(), SAS2::_3();
If you really need a hash like structure you may wanna try investigate the %SAS:: hash to grep all functions starting with an underscore.
print map {$_->()} grep {/::_/} values %SAS::;
of course this map-grep operation could be a method of your object ...
UPDATE: expanded code examples | [reply] [d/l] [select] |
Re: Dynamic Hash value
by arc_of_descent (Hermit) on Apr 21, 2010 at 07:48 UTC
|
You can create scalar references to $ini and $last, and use these references in your %results hash. Then when you change the values of $ini and $last, the hash will refer to the changed values. Read up on references here - perlref
my $ini = 5;
my $ini_ref = \$ini;
print $$ini_ref; # outputs 5
$ini = 6;
print $$ini_ref; outputs 6
| [reply] [d/l] |
|
no in this case it's not that simple because the scalars are not only referenced but also part of a calculation.
| [reply] |
Re: Dynamic Hash value
by LanX (Saint) on Apr 21, 2010 at 07:52 UTC
|
Yes it's possible to automatically propagate any change of your scalars to the hash using Tie::Scalar.¹
But this technique is certainly not appropriate for a beginner.
¹) or Tie::Hash like others mentioned, that depends on if you wanna push or pull the changes. | [reply] |