Beefy Boxes and Bandwidth Generously Provided by pair Networks
Just another Perl shrine
 
PerlMonks  

Re^2: reduce like iterators

by LanX (Saint)
on Jan 03, 2011 at 18:50 UTC ( [id://880234]=note: print w/replies, xml ) Need Help??


in reply to Re: reduce like iterators
in thread reduce like iterators

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

Replies are listed 'Best First'.
Re^3: reduce like iterators
by ikegami (Patriarch) on Jan 03, 2011 at 19:54 UTC

    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

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

        Your always free to not give it a name, leaving it as

        my @b; for (@a) { push @b, $_ if !@b || $_ ne $b[-1]; }
        or
        my @b = list_reduce { 0, $a || $b ne $_->[-1] ? $b : () } 1, @a;

        But they're not very readable.

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

        You complain that there's "a lack of iterators allowing to compare successive elements", yet you wouldn't want to use them if they existed?

Re^3: reduce like iterators
by ELISHEVA (Prior) on Jan 03, 2011 at 20:04 UTC

    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

        How is memorizing a new special var any different than memorizing a new BLOCK LIST function name? Either way, you are having to memorize something new. Also depending on how you define your block list function, you are effectively making $a, $b, or $_ into a special purpose variable of your own choosing.

        Also I'm not sure I understand how you separate the notion of special variable from block function/syntax. Special variables generally are part of a process and the process drives the variables. Regexs are complicated processes with lots of mid-process data so they have lots of special variables. Sort is fairly simple, so it has just two $a and $b. But in each case, accompanying the special variable is a function or special syntax. $1 is associated with the syntax of a regular expression. $_ is associated with sort, grep, map, and for not because the variable has special meaning in and of itself, but because each of these function need only a current list member and $_ is symbol used when we need the current item of the list.

        If we were to start adding special variables to grep/sort/map and other list processing functions, I fear we'd bloat the amount of information that Perl would have to track on each iteration. I suppose the bloat could be avoided if Perl could decide what information to track by surveying the contents of the block and any special variables used within. So for example, if $N was reserved for run count, it would only track run count if the grep/map/foreach block contained $N. Is that the kind of thing you are getting at?

        There are so many possibilities of things one might want to track where would it stop? Run length? Cumulative frequency of the current value? Minimum found so far? Maximum found so far? Moving average? Wouldn't making all of these part of the language, each with its own special symbol make the language more complex? Wouldn't it be wiser to stick with the minimum number of symbols needed to do the job and let those who need more add them via the block/list syntax? An iteration through a list has to have a current member or else it makes no sense as an iterator. The special variable $_ is essential. A sort process needs two items to compare otherwise there is nothing to sort. $a and $b are essential to the process. But other "state of the list" variables are not. They are application dependent and perhaps should be left to applications to define on an as needed basis.

        I guess I still don't get what you are striving for, design wise. A reflection on the value of different kinds of syntax elements? How best to use the tools at hand in Perl? The ideal minimal set of iterators, whether they be represented by new block function names or new special variables or some combination of the two?

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others imbibing at the Monastery: (9)
As of 2024-04-23 17:51 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found