Beefy Boxes and Bandwidth Generously Provided by pair Networks
Problems? Is your data what you think it is?
 
PerlMonks  

Re^3: reduce like iterators

by LanX (Saint)
on Jan 16, 2011 at 11:22 UTC ( [id://882524]=note: print w/replies, xml ) Need Help??


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

Try @orig starting with undef.

Also see the OP for the "semi-predicate problem" discussion.

If this seems too theoretical for you, consider the practical task to do of a run-length encoding of sparsely set arrays. (undef is a real value)

Cheers Rolf

Replies are listed 'Best First'.
Re^4: reduce like iterators
by Anonymous Monk on Jan 17, 2011 at 22:47 UTC

    Good point about the initial value -- I forgot about that.

    It can be specially handled decently, though, something like:

    my @new = my $p = shift @orig; push @new, grep { $p = $_ or 1 if $p ne $_ } @orig;
Re^4: reduce like iterators
by furry_marmot (Pilgrim) on Jan 18, 2011 at 23:52 UTC

    Shoot! I totally get the semi-predicate problem, and you stated the problem clearly in the OP, but I thought I had a brainwave and rewrote my UPDATED code, which had actually accounted for the problem.

    So anyway, I re-read the entire thread and I sort of get why you'd want, say, a $^PRE special variable. But it is so trivial, I don't see why you'd bother. You are simply dealing with a list in pairwise fashion, using a previous value to evaluate a current value. Eliminating adjacent dupes is trivial...

    @new = map { $p ne $_ ? $p = $_ : () } @orig;
    except for an initial undefined value, but only because $p is initially undefined. So you define it and it works. And it's easy to remember.
    $p = 'supercalifragilistic'; @new = map { $p ne $_ ? $p = $_ : () } @orig;
    You could define a uniq_adj function...
    use strict; sub uniq_adj { my $p = 'supercalifragilistic'; return map { $p ne $_ ? $p = $_ : () } @_; } my @orig = (undef, undef, qw(a a b b c 0 c d d u u 0 0 "0" "0" '0' + '0')); my @new = uniq_adj @orig; print "'", join ("' '", @new), "'\n"; __END__ Prints --> '' 'a' 'b' 'c' '0' 'c' 'd' 'u' '0' '"0"' ''0''

    I printed with single quotes to show where undef's are being printed. Note that 0, "0", and '0' are preserved. It's very generalizable. I predefined $p, but isn't that less work than having Perl do it through a built-in? I read through the entire thread again and it seems to fit the bill. Is this kind of what you're looking for?

    Regardless, cheers!

    --marmot
      Your surely aware that replacing undef with a "magic" string is not a solution of the semi-predicate problem, because the magic string can also be an element of the processed list.

      Cheers Rolf

        In general and in theory, no.

        But lots of people have so done, and it works out reasonably well in practice. For a random example Dominus used char(20) for this purpose in the widely used Memoize. (Then documented the limitation.) This code is significantly faster than a robust escape mechanism would have been, and he provided a mechanism to fix the potential bug if you needed to.

        I don't know about "magic", but sure, I understand it's not a solution to the semi-predicate problem, but all the solutions are one kind of workaround or another, aren't they? Wouldn't a $^PRE built-in be undef at the start of your grep{} block and cause you the same problem? When it comes to the initial element of the list, wouldn't you still have the same problem no matter what kind of built-in variables you had available to you?

        reduce really doesn't make sense because that performs a function on the results of the previous run of the function. $a accumulates...something, but you end up with one value, not a new list. What you want is more like a grep -- deciding whether to allow a current value through based on a previous value.

        You can write a function that takes tuples and special cases $a, so it won't be skipped, but you didn't think that was elegant.

        You can write a function that initializes $p (or whatever you call it), and hide the details in the function, but you didn't like that either.

        In the end, you have to initialize $p, special-case the first element, or write much more complicated code just to avoid initializing $p. It all amounts to the same thing, so why not keep it simple? Obviously the semi-predicate problem is a very real concern, but it's also pretty trivial...

        My two cents...

        --marmot

Log In?
Username:
Password:

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

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

    No recent polls found