Language: EN

programacion-ambito-de-las-variables

What is the scope of variables

When working with variables in programming, it is essential to understand the scope of the variable. This is one of the topics that many programmers find difficult to understand, when, in reality, it is very simple.

The scope of a variable is the context in which a variable exists and can be used. Outside of its scope, the variable does not exist and, therefore, we cannot use it.

As we saw when we looked at the life cycle of a program, a variable has its own “life cycle”. In general, during our program,

  • We declare / create the variable
  • We use the variable
  • The variable is destroyed

The area where we can use the variable is its scope. In general (spoiler!), in practically all modern languages the variable exists from the moment it is created, until the block in which it is defined ends.

It is intuitive to think that we cannot use a variable before creating it (although we will see that some languages are special, right JavaScript?).

The other missing factor is when the variable ceases to exist. Unless we release it manually, the variable is automatically destroyed when it exits the block where it is created.

programacion-ambito-variable

So the scope of existence of the variable includes all the instructions and nested blocks that are found between the creation and destruction of the variable, which usually occurs at the end of the block in which it was created.

Put in code form, it is something like the following:

// not available here ❌
{
   // not available here ❌

   int myVariable = 5;
   // available here ✔️
   
   {
	   // available in this inner block ✔️
   }
}
// not available here ❌

Examples of variable scope in different languages

Let’s see the scope of the variable in different languages

In C#, the scope of a variable can be a code block, a function, or the entire class:

class EjemploClase 
{
   int variableDeClase = 5;

   void EjemploFuncion()
   {
      int variableDeFuncion = 10;
	 
      if(condition)
      {
         int variableDeBloque = 15;
      }
   }
}

Here

  • variableDeClase would be available throughout the EjemploClase class
  • variableDeFuncion would be available within the EjemploFuncion function
  • variableDeBloque would be available within the conditional

This behavior is more or less standard in every programming language.

For example, in Python

def ejemplo():
   variableDeFuncion = 10
   
   if True:
      variableDeBloque = 15
      print(variableDeBloque)
      
   print(variableDeFuncion)

JavaScript deserves its own “honorable mention” when it comes to the scope of variables. In its early versions, it had the “great idea” of being different from the others (spoiler, it didn’t go well 😅)

Explaining it in depth I will leave for when I do a course on JavaScript but, in summary, at first, variables in JavaScript had function scope, instead of block scope (pause for applause 👏👏).

if (true) {
   var x = 20;   // ¡¡this has function scope, not block scope 😱
}

This led to many strange and unexpected situations. It caused so many problems that in subsequent versions they had to try to fix it by introducing let and const, which work in block scope.

if (true) {
   let x = 20;   // this has block scope
}

In summary, there are few languages in which the scope of the variable is not the block (as far as I can think, BASIC and JavaScript). But since JavaScript is so widely used and important, it seemed important to emphasize it.

Global variables and local variables

In many programming languages, it is possible to define global variables, which can be accessed from any part of the program.

For example, let’s assume an Arduino program (which is based on C++)

int globalVariable = 10; // Declaration of a global variable

void setup() {
}

void loop() {
  // Show the value of the global variable in the serial monitor
  Serial.println(globalVariable);
}

For example, here we would have an example of global variables in Python

x = 10

def myfunc():
  # Show the value of the global variable in the console
  print(x)  

Although Python also has its “special” things. If we wanted to modify the value of x, instead of just consulting it, we should use the global keyword. But that’s for when I do a course on Python.

In JavaScript

let globalVariable = 10;

function updateGlobalVariable() {
  // Show the value of the global variable in the console
  console.log(globalVariable)
}

In general, almost all languages have global functions implemented, in one way or another, or with their language peculiarities. But they have them.

Cleaning tips Tips

It is often said that using global variables is a bad practice. Well, it is not always a bad practice. In fact, it is not only that they have their utility, they are necessary for the program to work (the entry point, for instance, is a global variable).

If you stop to think, there is actually no conceptual difference between a global variable and a local variable. A global variable also has its scope. It’s just that since it is outside of any block, its “block” is the entire program.

What is true is that overusing global variables is a bad practice. In general, we should always use local variables whenever possible, and use global variables in the few cases where it is truly essential.

Let’s see a very simple example, in a hypothetical machine that reads a temperature and uses a function to modify it.

int rawTemperature; // Declaration of a global variable

void correct_temperature() {
   rawTemperature *= 2;  // Do anything with your global variable
}

void loop() {
  rawTemperature = 10;

  correct_temperature();
}

Making all variables global is quite dirty… well, you know what I mean. It is much better if instead of that, we use local variables, and each function has the parameters it needs and returns.

int correct_temperature(int temperature) {
   return temperature * 2;
}

void loop() {
  int rawTemperature = 10;
  int corrected_temperature = correct_temperature(rawTemperature);
}

In the long run, the code is much more maintainable, better isolated, reusable, etc etc

Low-level explanation Advanced

Let’s try to explain briefly how the scope of a variable works and the reasons for its existence, at a low level.

In compiled languages like C++, when we create a variable within a block, it is stored in the stack. Regardless of whether the “content” of the variable goes to the heap, the variable itself always goes to the stack.

Then the block does its actions and things. When the block ends, the stack must be clean and in a neutral state. During the process, local variables are eliminated.

That is, at a low level, the fact that variables are always associated with the block in which they are created is an imposition due to the way the processor works.

In semi-compiled languages like Java or C# or interpreted languages like Python, it would not have to be that way. Here the memory manager or the interpreter could decide to store the variable after the block has ended.

In fact, we have seen that JavaScript, at the beginning, did not follow this rule… and it didn’t go well.

However, the same rules have been followed because they are intuitive and practical. The fact that a variable has local significance and ceases to exist when it goes out of scope seems to make sense, right?

This encourages code reuse and reduces the possibility of errors. Therefore, the most ‘modern’ programming languages continue to maintain the same rules, although, unlike lower-level languages, they are strictly not required to comply with them.