Beefy Boxes and Bandwidth Generously Provided by pair Networks
Clear questions and runnable code
get the best and fastest answer
 
PerlMonks  

Re: reduce like iterators

by ELISHEVA (Prior)
on Jan 03, 2011 at 18:27 UTC ( [id://880229]=note: print w/replies, xml ) Need Help??


in reply to reduce like iterators

This is fairly easy to implement and wrap in a sub, even with the undefs. Once the sub is written you are back to having a one-liner. What would you like that this wouldn't do?

use strict; use warnings; sub compress { my $x; map { if (!defined($x)) { defined($_) ? ($x = $_) : () } else { defined($_) && ($x eq $_) ? () : ($x = $_) } } @_; } my @aData=(qw(a a a a b c c a a d e e e e), undef, undef, qw(f g g)); my @aCompressed = compress @aData; print "compressed: @aCompressed\n"; # outputs a b c a d e undef f g

Or if you want to play golf (though others I'm sure can do better)

sub compress { my$x;map{defined($x)?(defined($_)&&($x eq$_)?():($x=$_) +):defined($_)?($x=$_):()}@_; }

Update: added golf

Update:: fixed mistake - undefs were strings.

Replies are listed 'Best First'.
Re^2: reduce like iterators
by LanX (Saint) on Jan 03, 2011 at 18:50 UTC
    Sure, I also did a function like this in the emacs help group

    But I was asking about designing a generic iterator solution, opening a variety of applications and augmenting readablity

    already a reduce_list {BLOCK} LIST variant of reduce could be sufficient in this case

     reduce_list { $a ne $b } qw(a a a a b c c a a d e e e e undef undef f g g)

    another application would be Haskells group iterator which partitions into successive groups:

    group [1, 1, 1, 1, 2, 3, 3, 1, 1, 4, 5, 5, 5, 5] ==> [[1,1,1,1], [2], [3,3], [1,1], [4], [5,5,5,5]]

    Simpling allowing access to the previous iteration easily would help implementing this with part from List::MoreUtils

     part { $a eq $b } LIST

    or

     part { $^PRE eq $_ } LIST

    Without the need to invent and name a whole new group of iterators.

    Cheers Rolf

      Your reduce_list is named similarly to reduce, but bears no resemblance since it doesn't to reduce at all.

      • reduce allows an arbitrary state to be passed from one pass to another. Your reduce_list doesn't.

      • reduce can return any value, not just the input. reduce_list can return at most one scalar, and it can only be the input. (That's not very "listy"!)

      Because of those reasons, reduce is a general purpose function. (It can implement any other function in List::Util.) Your reduce_list is just grep with access to the last element.

      This accounts for the differences with what I suggested it should look like.

        As already stated in the OP the need to appropiately name a whole new family of reduce-like iterators is an extra problem.

        At least for me it's more complicated than implementing them.

        But if it's easier for you to baptize reduce-like maps, greps, parts, and so on in a quick post, I would appreciate to hear your suggestions

        If I was forced to chose only one implementation I would certainly chose a reduce like map, like you did, because it has the biggest flexibility.

        But I'd prefer to have a solution where map is still named map and grep ist still grep!

        IMHO extra options and special vars should activate and supply the needed functionality.

        Cheers Rolf

      Perl also lets you use parameters to roll your own block syntax. Here is a slightly different definition that would allow you to do arbitrary operations on the first element of each run in a list:

      Or if you want to be able to work with the current run value ($b) and the previous run value $a, you could do something like this:

      There is almost no limit to what you could create. For example, if you wanted to be able to group items, you could additionally track the number of items in each run and set $_ to number of items in the current run:

      Would that do what you want?

      Update: added yet another block iterator, this time one that could be used for generating groups as in the Haskell function above.

      Update: put in readmore tags

      Update: fixed 3rd example so it prints count of current (not previous) run.

        this is a reply I wrote about an hour ago but forgot to post, thankfully I was able to find the preview in the history of one of my tabs, sorry if it's not up to date to your updates

        > Would that do what you want?

        Thanks Elisheva, but I don't have an implementation problem.

        I'm well aware that there are plenty of possibilities to realize a specialized function, e.g. with a prototyped code-block like you demonstrated.

        I'm rather interested in a good design, to produce elegant, expressive and easily maintainable code.

        As I said, I wouldn't like to reimplement each function in List::Util and List::MoreUtils as "reduce like" versions, with the additional problem to find and memorize new names for those functions.

        Thats why I'm meditating about additional special vars to augment those functions with the needed tweaks in a orthogonal way, without breaking the original functionality.

        As an analogue, see how many RegEx-functions other languages like PHP have to implement special functionalities, which are realized in Perl with special vars or modifiers.

        Cheers Rolf

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://880229]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others studying the Monastery: (6)
As of 2024-03-29 14:08 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found