Beefy Boxes and Bandwidth Generously Provided by pair Networks
P is for Practical
 
PerlMonks  

I crashed 99 bottles.. the dot was the point (multiconcat)

by Discipulus (Abbot)
on Apr 19, 2019 at 19:25 UTC ( #1232826=perlmeditation: print w/replies, xml ) Need Help??

Hello folks!

recently I visited code-golf.io and i found my (terrible) 99 bottles of beer marked as broken. A lot of glass on the floor..

I tried it locally and it was correct on perl 5.24 (and 5.26) but no more on 5.28 Basically the heart of the code was:

$n=4; print $n." -- ".(--$n||'no more'),".\n" while $n; # output on perl 5.26 5.24 and before 4 -- 3. 3 -- 2. 2 -- 1. 1 -- no more. # output on perl 5.28 3 -- 3. 2 -- 2. 1 -- 1. 0 -- no more.

I tried looking in perldelta if something changed in autoincrement autodecrement between versions, but nothing.

The rule of thumb in official docs goes: This also means that modifying a variable twice in the same statement will lead to undefined behavior.

But I supposed this was not the case: I was using and modifying it, not modifying it twice.

The cloister was empty and only brother Eily was here to help (thanks) pointing me to undefined behaviour associated with some case of autodecrement.

Then I knocked the irc door where (when I finally was able to reduce the failing code to the above) the wise Grinnz bet on the issue was due to multiconcat performance enhancement. Tadąaaa!

Is not the autoincrement/autodecrement to had changed but the time where concatenation happens: infact the above code with commas behaves the same across versions:

$n=4; print $n." -- ",(--$n||'no more'),".\n" while $n; #^--- is a comma now! # output on perl 5.28 4 -- 3. 3 -- 2. 2 -- 1. 1 -- no more.

So, be aware of the above my friends! From 5.28 onward the dot can be the point!

L*

PS

the above provoked a small flame on irc but a wise named integral posted an interesting piece of code (I admit I do not understand it, but look for concat/multiconcat):

use B::Concise; sub sample { $n=4; print $n." -- ".(--$n||'no more'),".\n" while $n; } + B::Concise::compile('-exec', "sample", \&sample)->(); __DATA__ # output in perl 5.24 main::sample: 1 <;> nextstate(main -12 99bottles.pl:2) v:{ 2 <$> const[IV 4] s 3 <#> gvsv[*n] s 4 <2> sassign vKS/2 5 <;> nextstate(main -12 99bottles.pl:2) v:{ 6 <0> enter 7 <#> gvsv[*n] s 8 <|> and(other->9) K/1 9 <0> pushmark s a <#> gvsv[*n] s b <$> const[PV " -- "] s c <2> concat[t3] sK/2 d <#> gvsv[*n] s e <1> predec sK/1 f <|> or(other->g) sK/1 g <$> const[PV "no more"] s h <2> concat[t5] sKS/2 i <$> const[PV ".\n"] s j <@> print sK k <0> unstack s goto 7 l <@> leave K* m <1> leavesub[1 ref] K/REFC,1 B::Concise::compile(CODE(0x5ef428)) 1 <;> nextstate(main -12 99bottles.pl:2) v:{ 2 <$> const[IV 4] s 3 <#> gvsv[*n] s 4 <2> sassign vKS/2 5 <;> nextstate(main -12 99bottles.pl:2) v:{ 6 <0> enter 7 <#> gvsv[*n] s 8 <|> and(other->9) K/1 9 <0> pushmark s a <#> gvsv[*n] s b <$> const[PV " -- "] s c <2> concat[t3] sK/2 d <#> gvsv[*n] s e <1> predec sK/1 f <|> or(other->g) sK/1 g <$> const[PV "no more"] s h <2> concat[t5] sKS/2 i <$> const[PV ".\n"] s j <@> print sK k <0> unstack s goto 7 l <@> leave K* m <1> leavesub[1 ref] K/REFC,1 # output in 5.28 main::sample: 1 <;> nextstate(main -8 99bottles.pl:2) v:{ 2 <$> const[IV 4] s 3 <#> gvsv[*n] s 4 <2> sassign vKS/2 5 <;> nextstate(main -8 99bottles.pl:2) v:{ 6 <0> enter 7 <#> gvsv[*n] s 8 <|> and(other->9) K/1 9 <0> pushmark s a <#> gvsv[*n] s b <#> gvsv[*n] s c <1> predec sK/1 d <|> or(other->e) sK/1 e <$> const[PV "no more"] s f <+> multiconcat(" -- ",-1,4,-1)[t5] sK g <$> const[PV ".\n"] s h <@> print sK i <0> unstack s goto 7 j <@> leave K* k <1> leavesub[1 ref] K/REFC,1 B::Concise::compile(CODE(0x4fe6e0)) 1 <;> nextstate(main -8 99bottles.pl:2) v:{ 2 <$> const[IV 4] s 3 <#> gvsv[*n] s 4 <2> sassign vKS/2 5 <;> nextstate(main -8 99bottles.pl:2) v:{ 6 <0> enter 7 <#> gvsv[*n] s 8 <|> and(other->9) K/1 9 <0> pushmark s a <#> gvsv[*n] s b <#> gvsv[*n] s c <1> predec sK/1 d <|> or(other->e) sK/1 e <$> const[PV "no more"] s f <+> multiconcat(" -- ",-1,4,-1)[t5] sK g <$> const[PV ".\n"] s h <@> print sK i <0> unstack s goto 7 j <@> leave K* k <1> leavesub[1 ref] K/REFC,1

There are no rules, there are no thumbs..
Reinvent the wheel, then learn The Wheel; may be one day you reinvent one of THE WHEELS.

Replies are listed 'Best First'.
Re: I crashed 99 bottles.. the dot was the point (multiconcat)
by tybalt89 (Prior) on Apr 19, 2019 at 21:18 UTC

    One always did have to look out for devilish things like this:

    perl -le 'print $n, --$n, $n = 6'
Re: I crashed 99 bottles.. the dot was the point (multiconcat)
by Laurent_R (Canon) on Apr 26, 2019 at 10:17 UTC
    It looks like an old and well-known (albeit somewhat obscure and tricky) problem in C (and C++): sometimes, you have to introduce sequence point (see for example https://en.wikipedia.org/wiki/Sequence_point and http://www.c-faq.com/expr/seqpoints.html for more details) to make sure that all side-effects from previous evaluations are completed and that no-side effect from subsequent evaluations has been performed. If you don't do that, the behavior is undefined, which means that different C compilers may yield different results and still comply with the C standard; and I have actually observed such discrepancy of behaviors many years ago (some time in the last decade of last century) between two C compilers.

    One of the typical ways to introduce a sequence point in such an expression is to add a comma. This is presumably the reason why your version with commas works as expected.

    Update: fixed a couple of typos.

Re: I crashed 99 bottles.. the dot was the point (multiconcat)
by pwagyi (Monk) on Apr 29, 2019 at 06:23 UTC

    Normally relying on such order of evaluation should be avoided in any language. another example would be subroutine arguments evaluation order &f($x,++$x, func_that_may_do_somethingto_x(\$x) );

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlmeditation [id://1232826]
Front-paged by haukex
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others examining the Monastery: (5)
As of 2022-08-13 20:31 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found

    Notices?