Programming Languages – Declaring Variables in Python and PHP

debuggingdeclarationserrorsprogramming-languages

The question is how to cope with absence of variable declaration in Python, PHP, and the like.

In most languages there is a way to let the compiler know whether I introduce a new variable or refer to an existing one: my in Perl (use strict) or \newcommand vs. \revewcommand in LaTeX. This prevents from two major sources of errors and headache:

(1) accidentally using the same name of a variable for two different purposes, such as in (PHP)

$v = $square * $height;
<...lots of code...>
foreach ($options as $k => $v)
    echo "For key $k the value is $v\n";
<...lots of code...>
echo "The volume is $v";

or a lot nastier (PHP)

$a = [1, 2, 3];
foreach ($a as $k => &$v)
    $v++;
foreach ($a as $k => $v)
    echo "$k => $v\n";

(can you see a bug here? try it!); and

(2) prevent from typos (PHP):

$option = 1;
$numberofelements = 1;
if ($option)
{
    $numberofelenents = 2;
}
echo $numberofelements;

(can you see a bug here? PHP will execute silently).

Using something like my (Perl)

use strict; 
my $option = 1;
my $numberofelements = 1;
if ($option)
{
    $numberofelenents = 2;
}
say $numberofelements;

(Perl will immediately report the bug) is a tiny effort and HUGE benefit both in debug time and (much more importantly) in losses (potentially huge) from incorrect programs.

However, some languages, notably Python, PHP, and JavaScript, do not give any protection from these types of bugs.

My question is how can we effectively cope with this?

The only way I can foresee is to create two functions (PHP):

function a ($x)
{
    if (isset ($x))
        die();
    else
        return &$x;
}

and

function the ($x)
{
    if (isset ($x))
        return &$x;
    else
        die();
}

and use them always:

a($numberofelements) = 1;
the($numberofelenents)++;
say the($numberofelements);

but of course this is extremely cumbersome. Any better way of effectively protecting from such errors?

No, "use another language", "be careful and don't make errors", and "split your code in tiny functions" are not good answers (the latter may protect from the errors of type 1 but not type 2).

Best Answer

In my experience, there are three ways to prevent the problems you described above:

  1. Limit the scope of your variables
  2. Name your variables something meaningful and descriptive
  3. Use a pre-compiler to notify of any errors (Doval mentioned pylint for Python)

1) Limiting the scope of your variables will limit the first error. You will have fewer variables that have the possibility of containing the same name. Odds are that you won't have any collisions. You can limit scope by declaring variables only in the scope that they will be used. The reason this works is because variables will be disposed of as a result of the natural cycle in your code. I've provided an example below for clarify.

class:
    classVariable = "classVar";

    function ThisIsAFunction(functionVar) {
        var functionVar2 = "functionVar2";
        if functionVar > functionVar2 :
            var ifStatementVar = "ifStatementVar";

            for i in range(0,2):
                ifStatementVar += i;
            // i will go out of scope here
        // ifStatementVar will go out of scope here
    // functionVar and functionVar2 will go out of scope here

2) Naming your variables something meaningful will go a long way to preventing re-use of the same variable name. The key in naming your variables is to make them specific enough that their name cannot be reused. When refactoring code it is a good idea to look for function, variable and class names that can be renamed to better reflect their purpose and meaning. An example of good variable names is the following:

function GetSumOfTwoIntegers(intFirstNum, intSecondNum):
    return intFirstNum + intSecondNum;

There is a lot of discrepency when deciding on good names. Everyone has their own style. The main thing to ensure is that you it is clear to yourself and others what the method, parameter or class is supposed to do and be used for. GetSumOfTwoIntegers as a method name tells anyone calling this method that they need to pass in two integers and they will be receiving the sum as a result.

3) Finally, you can use a pre-compiler to tell you of any mistakes that have been made. If you are using a good IDE, it will notify you of any errors. Visual Studio uses Intellisence to let the developer know of any errors before compiling. Most languages have an IDE that supports this functionality. Using one would certainly solve your second problem.

The reason someone might choose to create the syntax of a language in a specific way is hard to determine. I can posture that in Python's case it was likely that the creator wanted to type less when writing code. It only takes a print statement to create a Hello World program in Python. Creating a comparable program in Java requires a lot more typing. Anyways, I don't really know why the creator chose this syntax.

Related Topic