Portée des variables

À l'intérieur des fonctions comme celle que nous venons d'écrire, vous avez le droit de manipuler trois types de variables :

  • Les variables d'entrée de la fonction. Vous ne pouvez pas modifier leurs valeurs ;

  • Les variables de sortie de la fonction. Vous devez leur affecter une valeur ;

  • Les variables locales. Ce sont des variables temporaires pour découper des calculs par exemple. Elles n'ont de sens qu'à l'intérieur de la fonction et ne seront pas «vues» de l'extérieur.

Variables locales

Par défaut, les variables créées sont locales. Cela signifie qu'elles ne sont accessibles que dans le contexte où elles ont été créées.

Dit autrement, le script principal et les différentes fonctions ont tous des workspaces spécifiques, et les variables créées dans le script principal sont dans l'espace mémoire du script principal, alors que les variables créées dans une fonction sont dans l'espace mémoire de la fonction.

De ce fait, on peut définir des variables dans un contexte, sans se soucier de l'existence de variables de même nom dans d'autres contextes.

Remarque

La séparation des espaces mémoires implique le passage de paramètres par arguments : en pratique, si l'on veut qu'une fonction inter-agisse avec une variable d'un script, il est nécessaire de passer la valeur de cette variable en tant qu'argument d'entrée de la fonction, et de récupérer la valeur de la sortie pour que le programme principal affecte cette valeur à sa propre variable locale.

Exemple

Prenons une exemple très simple. Définissons une fonction (dans un fichier cube.m) calculant la puissance cubique d'un tableau de valeurs :

1
2
3
function tableauSortie = cube(tableauEntree)
    tableauSortie = tableauEntree.^3 ;
end

Dans cette fonction, nous avons défini des variables d'entrée et de sortie ayant des noms évocateurs : tableauEntree et tableauSortie. Mais en pratique, nous allons utiliser cette fonction dans un script principal, sans nous soucier de ces noms, avec nos propres variables, dont les noms x et y sont choisis dans le contexte d'usage du script principal. Les valeurs de la variable x sont passées en argument de la fonction cube, qui retourne les valeurs calculées localement dans tableauSortie, et le script principal affecte ces valeurs à la variable y :

1
2
3
4
x = -pi:pi/50:pi;
y = cube(x);
plot(x,y) ;
xlabel('x') ;ylabel('y') ; title('y = x^3') ;
Tracé de la fonction cube
Tracé de la fonction cube

Complément

Dans le cas de fonctions imbriquées, les espaces mémoires de la fonction contenue et de fonction contenante sont identiques : c'est pourquoi toutes les variables de ces fonctions sont accessibles, et qu'il n'y a pas nécessité d'un passage de paramètres en arguments.

Variables globales

Imaginons maintenant que vous écriviez un script de commandes (le programme principal), et une fonction (dans un second fichier bien sûr), le script de commandes se servant de la fonction.

Si vous voulez passer une valeur du script de commandes à la fonction, vous devez normalement passer par une entrée de la fonction. Cependant, on aimerait bien parfois qu'une variable A du script de commandes soit utilisable directement par la fonction, sans passer par les arguments de la fonction.

Pour cela on utilise la directive global.

Syntaxe

Pour que des variables soient accessibles directement au delà du contexte local où elles ont été définies, il faut les déclarer comme étant global, avant de leur donner une valeur, ainsi que dans toutes fonctions où l'on veut aussi y accéder. La syntaxe de déclaration est :

1
global variable_1 variable_2 ... variable_n

Exemple

Prenons un exemple :

Vous disposez d'une corrélation donnant le \(C_p\) d'un gaz en fonction de la température :

\[C_p(T) = AT^3+BT^2+CT+D\]

et vous voulez en faire une fonction. On pourrait faire une fonction ayant cinq arguments d'entrée, pour \(T\), \(A\), \(B\), \(C\) et \(D\), mais il est plus naturel que cette fonction ait seulement \(T\) comme entrée.

Alors, comment passer \(A\), \(B\), \(C\) et \(D\) qui sont des constantes ? Tout simplement en déclarant ces variables en global, tant dans le fichier de commandes que dans la fonction Cp, et on leur affecte une valeur dans le script de commandes.

Ci-dessous le script principal :

1
2
3
4
5
6
7
8
9
10
11
12
13
%on déclare les variables comme global
global A B C D
  
%Paramètres de corrélation déterminés précédemment :
A = 9.9400e-8;
B = -4.02e-4;
C = 0.616;
D = -28.3;
  
T = 300:100:1000;         % Température en Kelvins
plot(T,Cp(T),'d:');         % On trace le CP en fonction de T
grid
xlabel('T'); ylabel('C_p'); title('Tracé de C_p(T), selon la corrélation');

et voici la fonction :

1
2
3
4
5
6
7
8
9
10
function y = Cp(T)
% fonction calculant le Cp en fonction de la température T
   
    global A B C D
    % on considère les paramètres de la corrélation connus, et
    % définis dans le script principal
   
    y = A*T.^3 + B*T.^2 +C*T + D;
 
end
Tracé de la fonction Cp
Tracé de la fonction Cp

Méthode

On peut toujours choisir de définir des variables en global, ou de les passer en arguments des fonctions.

Le contexte peut conduire à choisir l'une ou l'autre des méthodes. Dans l'exemple précédent, on a choisi de mettre en argument de la fonction Cp la grandeur physique dont dépend réellement la grandeur physique \(C_p\) (à savoir \(T\)), à l'inverse, on a défini en global les variables correspondant aux paramètres de corrélation (\(A\), \(B\), \(C\) et \(D\)), qui n'ont pas de sens physique, mais qui sont des valeurs déterminées a priori.

Conseil

De manière générale, il faut éviter de mettre les variables en global, si cela n'est pas nécessaire, parce que cela peut conduire à des erreurs difficiles à identifier.

Variables persistantes

Une variable persistante est une variable qui persiste dans l'espace mémoire (workspace) où elle a été créée, au delà de la durée de vie de son contexte local.

Dit autrement, une variable est par défaut locale à son contexte de création. Si une variable est créée dans une fonction, elle ne reste dans l'espace mémoire spécifique à cette fonction que le temps d'exécution de cette dernière. Une variable persistante reste en mémoire au delà de l'exécution de la fonction qui l'a créée, elle persiste.

Syntaxe

Pour que des variables soient persistantes, il faut les déclarer avec le mot clé persistent, avant de leur donner une valeur. La syntaxe de déclaration est :

1
persistent variable_1 variable_2 ... variable_n

Exemple

À titre d'exemple, nous allons définir une fonction qui incrémente un compteur à chaque fois que la fonction est appelée :

1
2
3
4
5
6
7
8
9
10
11
function [] = compteur()
    persistent passage
  
    if(isempty(passage))
        passage = 1 ;
    else
        passage = passage + 1 ;
    end
    disp(passage) ;
  
end

Si maintenant vous appelez cette fonction dans la fenêtre de commandes, à chaque appel, le compteur s'incrémente :

1
2
3
4
5
6
>> compteur
    1
>> compteur
    2
>> compteur
    3

La variable passage est bien persistante, mais elle est locale à la fonction, et elle n'est pas accessible dans un autre contexte. Si on appelle cette variable dans la fenêtre de commandes, on a une erreur :

1
2
>> passage
    Undefined function or variable 'passage'.

Remarque

Bien qu'une variable persistante reste en mémoire, elle reste malgré tout locale, et n'est accessible qu'à la fonction qui l'a créée.