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

Hello.

I used regex to solve one problem in contest. And received error message. Later I can't understand my mistake, how I have got it.

The problem. You are given an array of non-decreasing elements. Your task is to find (if any) two rightmost neighbouring elements whose difference is bigger than some number (c) and delete left element and all preceding elements. Then say how much elements have left.

It seems that simple procedural programming here is suitable much more than regex. But I tried with regex:

#!/usr/bin/perl use warnings; use strict; while(my $c = <>){ $_ = <>; s/ .*?(\b\d+)[ ] (?=(\d+)\b) (??{ print "[$1 $2]\n"; $2 - $1 <= $c ? 'X' : '' }) / (print "DELETED:[$&] REMAINS:[$']\n"), '' /egx; printf "NUMBERS:[%d:%s]\n", (length s/\d//gr), $_; print '-' x 10, "\n"; }
INPUT:
1 1000000000 5 1 1 1 2 2 2 1 1 3 5 7 9 10 1 1 2 3 4 5 28 31 36 43 5 1 3 8 14 19 26 33 1 1 2 3 4
OUTPUT:
NUMBERS:[1:1000000000 ] ---------- [1 1] [1 1] [1 2] [2 2] [2 2] [1 1] [1 2] [2 2] [2 2] [1 1] [1 2] [2 2] [2 2] [1 2] [2 2] [2 2] [1 2] [2 2] [2 2] [2 2] [2 2] [2 2] [2 2] [2 2] [2 2] NUMBERS:[6:1 1 1 2 2 2 ] ---------- [1 3] DELETED:[1 ] REMAINS:[3 5 7 9 10 ] [3 5] DELETED:[3 ] REMAINS:[5 7 9 10 ] [5 7] DELETED:[5 ] REMAINS:[7 9 10 ] [7 9] DELETED:[7 ] REMAINS:[9 10 ] [9 10] NUMBERS:[2:9 10 ] ---------- [1 2] [2 3] [3 4] [2 3] [3 4] [2 3] [3 4] [3 4] [3 4] NUMBERS:[4:1 2 3 4 ] ---------- [28 31] [31 36] [36 43] DELETED:[28 31 36 ] REMAINS:[43 ] NUMBERS:[1:43 ] ---------- [1 3] [3 8] [8 14] DELETED:[1 3 8 ] REMAINS:[14 19 26 33 ] [14 19] [19 26] DELETED:[14 19 ] REMAINS:[26 33 ] Can't coerce UNKNOWN to string in substitution iterator at ./coerce.pl + line 11, <> line 12.

Replies are listed 'Best First'.
Re: Can't coerce UNKNOWN to string in substitution iterator
by dave_the_m (Monsignor) on Oct 10, 2016 at 20:48 UTC
    Can't coerce UNKNOWN to string in substitution iterator
    That usually indicates a bug in perl itself: UNKNOWN indicates a freed or corrupted scalar value being accessed. It appears to be fixed in 5.24.0 by my context stack work, specifically commit v5.23.7-111-g1dfbe6b.

    Dave.

Re: Can't coerce UNKNOWN to string in substitution iterator
by choroba (Cardinal) on Oct 10, 2016 at 20:33 UTC
    I can confirm the behaviour in 5.18.2 and 5.20.1, but running the code in blead (720c8c4f57a8be0960c9068d899e9d111e143382) finishes the code without error.

    Check also splain for the message:

    Can't coerce UNKNOWN to string in substitution iterator at - line 11, +<> line 12 (#1) (F) Certain types of SVs, in particular real symbol table entries (typeglobs), can't be forced to stop being what they are. So you +can't say things like: *foo += 1; You CAN say $foo = *foo; $foo += 1; but then $foo no longer contains a glob.

    ($q=q:Sq=~/;[c](.)(.)/;chr(-||-|5+lengthSq)`"S|oS2"`map{chr |+ord }map{substrSq`S_+|`|}3E|-|`7**2-3:)=~y+S|`+$1,++print+eval$q,q,a,
Re: Can't coerce UNKNOWN to string in substitution iterator (splain, (??{}))
by beech (Parson) on Oct 10, 2016 at 20:34 UTC

    Hi

    Hmm splain has heard of the error (its in perldiag)

    I can't replicate the error in v5.16.1 but I can in v5.18.2

    The output starts to differ at line 59 , so I modify the input to just the part that makes error

    5 1 3 8 14 19 26 33

    Adding use re 'debug'; makes it run to completion , but output is not identical

    Now looking at the regex, and checking perlre,

    I see you're using (??{}) , but the return value (a regex pattern) is either X or nothing ... and there is no X in the input,

    so I switch to using (?{}) where return value isn't a regex pattern, and with this change both versions of perl produce the same output

    Now its not the same output as before with (??{}) but I dont think thats important

      I think the X is to prevent the regex from matching. Isn't there a better way to do that?

        Hi

        I think the X is to prevent the regex from matching. Isn't there a better way to do that?

        That is a good observation

        Maybe, there are http://perldoc.perl.org/perlre.html#Verbs for that, more on this at the end of this post

        Taking a second look at output of (??{ versus (?{

        As you can see all three versions end the final result of

        NUMBERS:[1:33 ]
        they just get there by different order of add/delete, not sure how important this is

        Only the crashing/buggy version returns something different when its able to complete under -Mre=debug

        Now back to verbs, using

        $2 - $1 <= $c ? '(*FAIL)' : '(*ACCEPT)'
        makes it fail in the exact same way, which is not too surprising

        Using *PRUNE or $2 - $1 <= $c ? '(*SKIP)' : '(*ACCEPT)' and its just like using (?{