Perl Best Practices [Electronic resources] نسخه متنی

اینجــــا یک کتابخانه دیجیتالی است

با بیش از 100000 منبع الکترونیکی رایگان به زبان فارسی ، عربی و انگلیسی

Perl Best Practices [Electronic resources] - نسخه متنی

Damian Conway

| نمايش فراداده ، افزودن یک نقد و بررسی
افزودن به کتابخانه شخصی
ارسال به دوستان
جستجو در متن کتاب
بیشتر
تنظیمات قلم

فونت

اندازه قلم

+ - پیش فرض

حالت نمایش

روز نیمروز شب
جستجو در لغت نامه
بیشتر
لیست موضوعات
توضیحات
افزودن یادداشت جدید







6.13. Complex Mappings


Use a subroutine call to factor out complex list transformations .


When a map, grep, or first is applied to a list, the block performing the transformation or conditional test can sometimes become quite complex[*]. For example:

[*] map blocks rarely start out complex, but the complexity of any critical piece of code will tend to grow over time. This fall from grace seems to be caused not so much by the Second Law of Thermodynamics as by the First Law of Murphy.



use List::Util qw( max );
Readonly my $JITTER_FACTOR => 0.01; # Jitter by a maximum of 1%
my @jittered_points
= map { my $x = $_->{x};
my $y = $_->{y};
my $max_jitter = max($x, $y) / $JITTER_FACTOR;
{ x => $x + gaussian_rand({mean=>0, dev=>0.25, scale=>$max_jitter}),
y => $y + gaussian_rand({mean=>0, dev=>0.25, scale=>$max_jitter}),
}
} @points;

This large block is very hard to read, especially since the final anonymous hash constructor looks more like a nested block. So the temptation is to use a for instead:


my @jittered_points;
for my $point (@points) {
my $x = $point->{x};
my $y = $point->{y};
my $max_jitter = max($x, $y) / $JITTER_FACTOR;
my $jittered_point = {
x => $x + gaussian_rand({ mean=>0, dev=>0.25, scale=>$max_jitter }),
y => $y + gaussian_rand({ mean=>0, dev=>0.25, scale=>$max_jitter }),
};
push @jittered_points, $jittered_point;
}

That certainly does help the overall readability, but it's still far from optimal. A better solution is to factor out the complex calculation into a separate subroutine, then call that subroutine within a now much simpler and more readable map expression:


my @jittered_points = map { jitter($_) } @points;

# and elsewhere...
# Add a random Gaussian perturbation to a point...

sub jitter {
my ($point) = @_;
my $x = $point->{x};
my $y = $point->{y};
my $max_jitter = max($x, $y) / $JITTER_FACTOR;
return {
x => $x + gaussian_rand({ mean=>0, dev=>0.25, scale=>$max_jitter }),
y => $y + gaussian_rand({ mean=>0, dev=>0.25, scale=>$max_jitter }),
};
}


/ 317