Beefy Boxes and Bandwidth Generously Provided by pair Networks
Do you know where your variables are?
 
PerlMonks  

$| pre and post increment and deincrement behavior

by bioMan (Beadle)
on Nov 30, 2005 at 19:24 UTC ( [id://513060]=perlquestion: print w/replies, xml ) Need Help??

bioMan has asked for the wisdom of the Perl Monks concerning the following question:

A question about elegant ways to split a sequence into groups of identical characters and a response by Roy Johnson using the idiom --$| with grep peaked my interest. I asked a follow-up question about the use of the idiom and was directed to Perl Idoms Explained -$|++, but this didn't really answer my question.

So I would like to explore this idiom a little further. The original question asked how to split a string like 'xx556xx' into groups of identical characters e.g. xx, 55, 6, xx. Roy Johnson proposed the idiom --$| with grep as a possible solution. I have used the idiom $|++ in scripts written for Windows to force fflush after every print statement. So I wondered if ++$| could have been used with grep to solve the problem above. My code for looking at $| with incrementing or deincrementing with either pre or post implementation is shown below.

my $str = 'xx556xx'; my @x = grep --$|, $str =~ m/((.)\2*)/g; report('pre-deincrement', @x); my @x = grep $|--, $str =~ m/((.)\2*)/g; report('post-deincrement', @x); my @x = grep ++$|, $str =~ m/((.)\2*)/g; report('pre-increment', @x); my @x = grep $|++, $str =~ m/((.)\2*)/g; report('post-increment', @x); sub report{ my ($type, @y) = @_; print "\n\nautoflush = ", $|, " , $type\n"; print join ',', @y; }

The results are:

autoflush = 0 , pre-deincrement
xx,55,6,xx

autoflush = 0 , post-deincrement
x,5,6,x

autoflush = 1 , pre-increment
xx,x,55,5,6,6,xx,x

autoflush = 1 , post-increment
xx,x,55,5,6,6,xx,x

Only the pre-deincrement works although the post-deincrement returns a list of the unique characters from the sequence.

The list xx,x,55,5,6,6,xx,x is the list returned by m/((.)\2*)/g so pre- and post-incrementation don't appear to be doing anything other than returning that list from the match statement.

I thought autoflush could only have values of 0 or 1 and am confussed by the results obtained. I understand that incrementing zero will return one, but what does deincrementing zero in $| return?

Does $| get reset to the default value after each list element is examined by grep? The pre- and post-increment results suggest this is not the case.

It appears I'm going to have to be much more careful about how I use $|.

Update

Thanks for the responses. They really helped. I was just playing with Data::Dumper, which also helped me understand how $| sets and resets with various applications of $|++ and $|--. It looks like using increment and deincrement on $| can allow for some pretty neat effects, but like a firecracker can blow up in your face if you're not careful :-).

Mike

Replies are listed 'Best First'.
Re: $| pre and post increment and deincrement behavior
by ikegami (Patriarch) on Nov 30, 2005 at 19:43 UTC

    grep has no relevance here.

    $|-- and --$| toggle the current value.
    $|++ and ++$| set the value to 1.
    $|-- and $|++ return the old value.
    --$| and ++$| return the new value.

    Normally, $| is set to 0.

    For example,

    print('$|--: '); $|=0; for (1..10) { print($|--, ' '); } print("\n"); print('--$|: '); $|=0; for (1..10) { print(--$|, ' '); } print("\n"); print('$|++: '); $|=0; for (1..10) { print($|++, ' '); } print("\n"); print('++$|: '); $|=0; for (1..10) { print(++$|, ' '); } print("\n");

    outputs

    $|--: 0 1 0 1 0 1 0 1 0 1 --$|: 1 0 1 0 1 0 1 0 1 0 $|++: 0 1 1 1 1 1 1 1 1 1 ++$|: 1 1 1 1 1 1 1 1 1 1

    Update: $toggle^=1 works just as well as --$|, but it's less obfuscated and has no side-effects:

    $,=", "; $\="\n"; @list = qw( a b c d ); $| = 0; print grep --$|, @list; # a, c $t = 0; print grep $t^=1, @list; # a, c

    Update: If you need every Nth term, try the following:

    $,=", "; $\="\n"; @list = qw( a b c d e f ); $n = 3; $t = $n-1; print grep !($t=($t+1)%$n), @list; # a, d
Re: $| pre and post increment and deincrement behavior
by Roy Johnson (Monsignor) on Nov 30, 2005 at 19:47 UTC
    Look for the word "magic" in Perl Idioms Explained - $|++ and look at diotalevi's reply to it as well. In short, ++$| is always true, and --$| always flips the value of $|. My use of it had nothing to do with flushing; only with the magically boolean nature of the variable.

    Caution: Contents may have been coded under pressure.
Re: $| pre and post increment and deincrement behavior
by GrandFather (Saint) on Nov 30, 2005 at 19:55 UTC

    Thie following code is instructive:

    use strict; use warnings; $| = 0; print $|++ . " " for (1..4); $| = 0; print "\n"; print $|-- . " " for (1..4);

    Prints:

    0 1 1 1 0 1 0 1

    Why does that happen? Well, from the documentation snippet referred to in Perl Idioms Explained - $|++, you see that the only legal values for $| are 0 and 1. When you increment $| to 2 it is set back to 1, so the 1 'sticks'. However, when you decrement $| to -1 the -1 is changed to 1. Next time it decrements from 1 to 0 - back where you started. A cheap toggle, so long as you are not interested in the effects on buffering.

    You might also consider:

    use strict; use warnings; my $x = 1; print $x ^= 1 . " " for (1..4);

    which prints:

    0101

    DWIM is Perl's answer to Gödel
Re: $| pre and post increment and deincrement behavior
by Anonymous Monk on Nov 30, 2005 at 21:19 UTC

    If you want $| to be 1, assign 1 to it. Pre- or post indcrement is unnecessarily "clever" and could bite you if $| doesn't happen to have the value you assume.

      Someone seems intent on repeating this particular piece of misinformation, so perhaps it's worth repeating (just this once) that it's incorrect.

      I do agree that $|++ is unnecessarily clever, since it might confuse an ignorant maintenenance programmer, and that $| = 1 is clearer. But it's simply wrong to say that it could “bite you if $| doesn't happen to have the value you assume”. It couldn't, for reasons that will be obvious to anyone who has understood this thread.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://513060]
Approved by Limbic~Region
Front-paged by Old_Gray_Bear
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others having an uproarious good time at the Monastery: (3)
As of 2024-04-26 08:19 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found