5

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).

  • The "why" has already been asked here. – Doval Jul 23 '14 at 13:15
  • @Doval: the main argument on that page is that the only thing that matters is how the code reads, and it reads OK without declarations. I totally disagree. I believe the main thing that matters is how the code executes (whether it has bugs), and absence of declarations has bitten me quite a number of times. – Alexander Gelbukh Jul 23 '14 at 13:29
  • I agree that the answer contained there may not be satisfactory to you, but you should avoid asking two questions at once, and one of the two you asked is already addressed there. It would be better to take up your objections there than to fork off a new discussion on the same topic here. – Doval Jul 23 '14 at 13:31
  • @Doval: OK, will edit the question to remove the why question and leave only the how question. – Alexander Gelbukh Jul 23 '14 at 13:54
  • 1
    +1 for excellent question and for pointing out that this issue costs money because of faulty programs. – Tulains Córdova Jul 24 '14 at 2:40
2

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.

  • OK, accepting this as answer. Though it's not exactly what I would like: I would like a way to detect typos in the language itself, such as PHP, and not having to use a complicated IDE for this. BTW, creating meaningful (thus, long) names increases the probability of typos; this is why I try to avoid long names. Ironically, it leads to more typing, too: you say the creator of the language wanted to save a couple of keystrokes per new variable and thus forced us to type longer names with every use of the variable, making the program more difficult to type and to read? Then rather stupid of him? – Alexander Gelbukh Jul 23 '14 at 15:04
  • 2
    I think the real reason Python was created is because someone really hated curley braces. Your right, longer names increase the probability of typos. – Cameron McKay Jul 23 '14 at 15:09
  • 1
    I wish he hated parentheses, too. After Perl, I find parentheses a big and unnecessary annoyance and source of bugs. – Alexander Gelbukh Jul 24 '14 at 0:30
2

In addition to the analysis tools, your IDE can also help you suss out these types of issues. I made the move to PyCharm because it handles these types of things much more effectively, than say, Eclipse & PyDev. It is a much more visual IDE that helps you prevent these issues.

0

There's only 3 solutions:

  1. Accept that you will occasionally have bugs because of this and deal with them as they occur
  2. Use a lint/static analysis tool (e.g. pylint)
  3. Use another language
  • 4. And use meaningful variable names. – eidsonator Jul 23 '14 at 13:25
  • Using meaningful variable names won't protect you from the occasional typo, and going over your code isn't a sure-fire way of spotting said typos since your brain is wired to correct them. I suppose a code review could catch them more reliably than the original writer, but a linter will still do the job better, faster, and is still applicable for one-man projects. – Doval Jul 23 '14 at 13:30
  • Ism't it that protecting from simple errors (not algorithmic ones, but just typos and re-using variable names) is one the main purposes or a programming language and a must-have property? – Alexander Gelbukh Jul 23 '14 at 13:32
  • I'm certain many people would disagree; it's not unusual for a C/C++ fan to defend manual memory management on the basis that they don't need a garbage collector to hold their hands. And if you do take that position, I question the decision to use dynamic typing, which also lets simple errors through. – Doval Jul 23 '14 at 13:34
  • Even in plain English we use articles for this: "There lived a king. The king had a daughter. The daughter was...": a declares an object and the indicates a reference. – Alexander Gelbukh Jul 23 '14 at 13:35

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.