The most important wrong thing is that you don't declare variables and don't have
use warnings;
use strict;
Also, using $a
and $b
is perilous since they are globals meant for sort
.
The my
variables $a
, $b
, $res
are lexical but the ones in the sub are yet other, global variables; this is because the sub is defined before the lexicals are declared. They are never initialized, so their undef
s overwrite lexicals on return. With use warnings;
added
Use of uninitialized value $b in multiplication (*) at .. [in sub]
Use of uninitialized value $a in multiplication (*) at .. [in sub]
Use of uninitialized value $a in concatenation (.) or string at .. [in print]
Use of uninitialized value $b in concatenation (.) or string at .. [in print]
The global $res
in the sub gets initialized to 0
and its return overwrites the lexical one.
If you were to put the code for the sub at the end it would "work," since lexicals get declared before the sub gets compiled so the sub sees them and uses them. But then again, if lexicals are in a "dynamic" scope that wouldn't work either; see this post. And altogether, using globals in a sub is not good.
Just declare variables in the subroutine and pass to it what it needs.
Then they exist only in the sub, also masking possible such names from outside scope. The sub has a well defined interface, returns values (scalars) which you assign as needed, and all is clear.
See Private Variables via my() in perlsub
Update
The title hints at use strict;
being in place, and a comment states that. Then the question would be about declaration of variables.
The strict pragma requires, among a few other things, that all variables be declared or fully qualified.
The $res
in the sub isn't declared, thus the compilation fails; the $a
and $b
exist as globals (but for use with sort
– don't use them for convenience). A declared variable is seen in included scopes but with functions this isn't quite so simple and you want to declare all variables inside a function.
Global-like variables declared with our are OK but their use brings about other issues. While globals do get used occasionally they are very rarely needed and are best avoided, since their use can ruin clean scoping which is one of critical principles in programming.
A useful reference is perldiag, which explains error messages. Or, use diagnostics in debugging runs, or better yet use splain or run the code with perl -Mdiagnostics ...