First I thougt about writing a longer meditation about iterators and semipredicate problem, but maybe a simple seek for perl wisdom is a better start.
In gnu.emacs.help someone asked
How would you code this simple list compression problem in Ruby:1.08 (**) Eliminate consecutive duplicates of list elements. If a list contains repeated elements they should be replaced with a single copy of the element. The order of the elements should not be changed.
Example:
?- compress([a,a,a,a,b,c,c,a,a,d,e,e,e,e],X). X = [a,b,c,a,d,e]
my first idea to solve it in perl was grep
DB<1> my $p; print grep { $p = $_ if $_ ne $p } (a,a,a,a,b,c,c, +a,a,d,e,e,e,e); abcade
but this approach fails for false list elements like e.g "0"!
A nice exmaple where a grep like map is better than the plain grep
DB<2> my $p; print map { $p ne $_ ? $p = $_ : () } (a,a,a,a,b,c,c,a +,a,d,e,e,e,e) abcade
But beside the need to lexicalize $p in the outer scope ...
using state wouldn't be more elegant :
DB<3> use feature "state"; print map { state $p; $p ne $_ ? $p = $_ : + () } (a,a,a,a,b,c,c,a,a,d,e,e,e,e) abcade
... it's still buggy if the compressed list was starting with undef values.
Thats a variation of the old Semipredicate problem:
"One can't find an initial value which is not also potentially a part of the iterated list!"
So I had a look into List::Util and the only appropriate approach was reduce
The first call will be with $a and $b
set to the first two elements of the list, subsequent calls will be
done by setting $a to the result of the previous call and $b to the
next element in the list.
Looks perfect, but reduce {} LIST only returns a scalar and List::MoreUtils doesn't seem to provide anything better¹.
(Sure I could use $a as an array-ref for accumulation, not very elegant...)
Temporary conclusion:
There seem to be a lack of iterators allowing to compare successive elements
And now I'm wondering about the best design ...
could a special variable like $^PRE generally help augmenting existing iterators, without the need to define and appropiately name a whole new family of reduce-like iterators?
( IMHO too many specialized functions like in LISP are hard to remember.)
something like
print grep { $_ ne $^PRE } (a,a,a,a,b,c,c,a,a,d,e,e,e,e); abcade
Thoughts?
Cheers Rolf
¹) couldn't find much more on CPAN...
In reply to reduce like iterators by LanX
| For: | Use: | ||
| & | & | ||
| < | < | ||
| > | > | ||
| [ | [ | ||
| ] | ] |