in reply to "a bit of sugar "(HOP)
Some examples may help...
I would write an iterator without either NEXTVAL() or Iterator() myself. Something like the following:
#!/usr/bin/perl -w use strict; use warnings; sub make_rand { my $x = 0; return sub { return $x++; # not very random }; } my $rng = make_rand(); for my $i (1..4) { my $x = $rng->(); print "$x\n"; }
sub {BLOCK} produces a reference to an anonymous subroutine and make_rand() uses this form as argument to return, returning a reference to an anonymous subroutine.
$rng->() dereferences the subroutine reference and calls the referenced subroutine.
NEXTVAL() does the same thing, but in a subroutine instead of directly. So the following also works:
#!/usr/bin/perl -w use strict; use warnings; sub NEXTVAL { $_[0]->() } sub make_rand { my $x = 0; return sub { return $x++; }; } my $rng = make_rand(); for my $i (1..4) { my $x = NEXTVAL ( $rng ); print "$x\n"; }
Iterator() deals with return sub {block}. You can define Iterator() without the prototype, in which case you would have to explicitly produce a subroutine reference as its argument. The following works:
#!/usr/bin/perl -w use strict; use warnings; sub NEXTVAL { $_[0]->() } sub Iterator { return $_[0] } sub make_rand { my $x = 0; return sub { return Iterator sub { return $x++; }; } my $rng = make_rand(); for my $i (1..4) { my $x = NEXTVAL ( $rng ); print "$x\n"; }
In this case, the reference to the anonymous subroutine is an argument to the subroutine Iterator rather than return, which only sees what Iterator returns. As Iterator returns its first argument without changing it, the reference to the anonymous subroutine is still being returned from make_rand().
Finally, with a prototype on Iterator(), you can dispense with the "sub" in its argument list and simply provide a "{BLOCK}". So the following also works.
#!/usr/bin/perl -w use strict; use warnings; sub NEXTVAL { $_[0]->() } sub Iterator (&) { return $_[0] } sub make_rand { my $x = 0; return Iterator { return $x++; }; } my $rng = make_rand(); for my $i (1..4) { my $x = NEXTVAL ( $rng ); print "$x\n"; }
They all work. The first will be slightly more efficient at run time, but usually not enough to matter. The latter may, depending on your sensibilities, be easier to understand and maintain. You can take your pick and use whichever tickles your fancy.
|
|---|
| Replies are listed 'Best First'. | |
|---|---|
|
Re^2: "a bit of sugar "(HOP)
by Wiggins (Hermit) on Mar 14, 2009 at 14:43 UTC | |
by ig (Vicar) on Mar 20, 2009 at 00:33 UTC |