CGI/Perl Guide | Learning Center | Forums | Advertise | Login
Site Search: in

  Main Index MAIN
INDEX
Search Posts SEARCH
POSTS
Who's Online WHO'S
ONLINE
Log in LOG
IN

Home: Perl Programming Help: Regular Expressions:
Recognition of numbers

 



GreetzFromWIT
New User

Sep 1, 2015, 3:52 AM

Post #1 of 6 (10045 views)
Recognition of numbers Can't Post

Hi all,

I get a strange error in one of my scripts and cannot think of the circumstances when this problem occurs. Do you have any idea?


Code
if (($params_in->{resolve_until_release}||"") =~ m/^(\d{4})\-(\d{2})$/ and $2 < 54) { 
do something…}

In an error log I see:
Use of uninitialized value $2 in numeric lt (<) at /srv/change/53/pfiff/pfiff_test/jetty/pfiff/cgi-bin/../modules/PAG/definitions_WF_2plus.pm line 796.


Now, AFAIK perl evaluates according to the defined precedences and to Wittgenstein :), i.e. in an expression "A and B", B is only evaluated if A is true. „=~“ has a higher precedence than „and“, perl is read left-to-right.

How can it happen that m/^(\d{4})\-(\d{2})$/ evaluates to true (i.e. the string is of the form YYYY-CW, both YYYY and CW contain only digits) and yet $2 is not initialized? Can $2 be the result of a previous assignment?

What is the magic string that leads to this error? One free beer for each correct answer….


FishMonger
Veteran / Moderator

Sep 1, 2015, 7:02 AM

Post #2 of 6 (10040 views)
Re: [GreetzFromWIT] Recognition of numbers [In reply to] Can't Post


Quote
Can $2 be the result of a previous assignment?

Yes it can.

Have you tried running the script through the debugger and inspected the values of the vars as each line is executed?


Quote
perl is read left-to-right

Not always. In some cases it needs to read/execute the right side first such as when the right side of the expression is the input for the left side expression.


GreetzFromWIT
New User

Sep 1, 2015, 7:15 AM

Post #3 of 6 (10037 views)
Re: [FishMonger] Recognition of numbers [In reply to] Can't Post

unfortunately I cannot debug this scenario, as this line is executed several hundred times a day and it is not possible to find out anymore exactly which data was processed at this time. The problem occurred only once and it seems that in 99.999999999% of all cases the statement works as expected. I had the suspicion that there must have been some very strange value in $params_in->{resolve_until_release}.

Thanks for the explanation about l-t-r, that's good to know. In this case however this does not seem to be the case.

On a second thought, even if $2 already had had a value before the comparison was executed, after the "and" $2 can only have a numeric value, am I right? How can it be not initialized?


FishMonger
Veteran / Moderator

Sep 1, 2015, 7:48 AM

Post #4 of 6 (10029 views)
Re: [GreetzFromWIT] Recognition of numbers [In reply to] Can't Post

Writing a short test script and input data would be easy enough to do to enable you to debug this issue.

IMO, the construct used in that conditional, which has lead to this problem (i.e., bug), is poor and should be refactored. Refactoring that conditional will resolve this bug in your code.


Code
($params_in->{resolve_until_release}||"")

You should ensure that $params_in->{resolve_until_release} is properly initialized prior to the conditional.

Doing that as well as moving the numerical test will simplify the conditional and allow for additional sub conditionals if needed in the future.

Code
if ($params_in->{resolve_until_release} =~ m/^(\d{4})\-(\d{2})$/) { 
if ($2 < 54) {
do something
}
elsif ($1 > 3333) {
do something else
}
}


Your current construct adds unnecessary complexity in the conditional and reduces maintainability.


GreetzFromWIT
New User

Sep 1, 2015, 9:06 AM

Post #5 of 6 (10025 views)
Re: [FishMonger] Recognition of numbers [In reply to] Can't Post

Yes, I did test this in a separate script using several input patterns but could never reproduce this behavior.

As it may happen depending on the incoming data that $params_in->{resolve_until_release} will either not exist or be any string or be the empty string or even undef, I use the construct ($var || '') quite often in comparisons and pattern matching; that will eliminate one additional variable or one if clause or one condition and possibly some brackets for the rest of the conditions. I tend to think that this is easier to read, because it becomes clearer what actual problem is dealt with in the complete if-clause. But I agree that this is arguable.


Anyway, thank you very much for your good advice, I will browse through my code and restructure all statements where $1/$2 are used so that they are only evaluated in the block after the condition and not inside the condition.

Best regards,
Mike


(This post was edited by GreetzFromWIT on Sep 1, 2015, 9:08 AM)


FishMonger
Veteran / Moderator

Sep 1, 2015, 9:33 AM

Post #6 of 6 (10018 views)
Re: [GreetzFromWIT] Recognition of numbers [In reply to] Can't Post

In the past I often used complex constructs like your conditional as a means to minimize the code. In doing so, occasionally it would come back to bite me with bugs which were difficult to troubleshoot, much like as is in this case.

I now put readability and maintainability above code brevity which has greatly reduced the amount of bugs in my code. Let perl golf and obfuscation be in the fun and "show off" code, not production code. :)

Since you're doing this in a loop, one way to fix the bug and keep it brief and readable and maintainable would be to do it this way.

Code
next unless exits $params_in->{resolve_until_release} 
and defined $params_in->{resolve_until_release}
and $params_in->{resolve_until_release} =~ m/^(\d{4})\-(\d{2})$/;



(This post was edited by FishMonger on Sep 1, 2015, 9:47 AM)

 
 


Search for (options) Powered by Gossamer Forum v.1.2.0

Web Applications & Managed Hosting Powered by Gossamer Threads
Visit our Mailing List Archives