Définition d'une sous-fonction

Nous avons vu qu'il peut être intéressant de créer des fichiers de fonctions, pour regrouper des commandes que l'on souhaite exécuter plusieurs fois, dans un même script principal, ou dans différents scripts.

Structurer un programme complexe, en un script principal qui appelle des fonctions spécifiques que l'on a définies pour réaliser des tâches bien déterminées, permet une évolution et une maintenance plus aisées de ce programme.

Un fichier de fonction .m peut contenir des sous-fonctions. Celles-ci ont la même structure qu'une fonction telle que définie précédemment, mais ne sont pas accessibles en dehors de la fonction principale. Les sous-fonctions favorisent la mutualisation de lignes de commandes, sans multiplier inutilement les fichiers.

Fonction locale

Soit une fonction définie dans un fichier .m.

Une fonction locale est une fonction définie dans le même fichier que la fonction principale (portant le nom du fichier) mais qui n'est utilisable que localement dans la fonction principale, ou par d'autres fonctions locales de ce même fichier.

Syntaxe

Les fonctions locales sont une succession de blocs fonctionnels contenus dans un fichier maFonction.m portant le nom de la fonction principale maFonction :

function [s_1 ... s_ns] = maFonction(e_1... e_ne)
    instructions ;
end
 
function [s_1 ... s_ms] = uneFonctionLocale(e_1... e_me)
    instructions ;
end
 
function [s_1 ... s_ps] = uneSecondeFonctionLocale(e_1... e_pe)
    instructions ;
end

Exemple

Dans l'exemple qui suit, nous définissons une fonction tribulle.m dont l'objectif est de trier un vecteur de valeurs, en ordre croissant ou décroissant. Cette fonction a vocation à être utilisée et ré-utilisée, l'écriture d'une telle fonction se justifie pleinement.

Pour définir cette fonction, nous avons décidé de séquencer notre code en sous-fonctions. Ces sous-fonctions sont utiles à la fonction tribulle, mais n'ont pas d'utilité en dehors de ce contexte, c'est pourquoi nous les avons définies comme sous-fonctions et non comme des fonctions spécifiques dans d'autres fichiers .m.

%% tribulle.m
% Fabien Baillon et Jean-Louis Dirion - Novembre 2014
%
% Cette fonction permet de trier un ensemble de valeurs.
% V est le vecteur de valeurs à trier.
%
% ordre est un caractère :
%       s'il vaut 'c', le tri sera par ordre croissant,
%       s'il vaut 'd', le tri sera par ordre décroissant.
%
% La méthode utilisée pour ordonner le vecteur V est le tri par bulle.

function V = tribulle(V,ordre)

    continu = true;

    while(continu)
        tri = false;
        switch ordre
            case 'c'
        	[V,tri] = trier_c(V,tri);
            case 'd'
            [V,tri] = trier_d(V,tri);
        end
        continu=tri;
    end

end
    

function [V,tri] = trier_c(V,tri)
	%% trier_c
	%
	% sous-fonction pour le tri croissant
    for indice=1:length(V)-1
        if(V(indice) > V(indice+1))
            [V,tri] = permute(V,indice);
        end
    end
end


function [V,tri] = trier_d(V,tri)
	%% trier_d
	%
	% sous-fonction pour le tri décroissant
    for indice=1:length(V)-1
        if(V(indice) < V(indice+1))
            [V,tri] = permute(V,indice);
        end
    end
end


function [V,tri] = permute(V,indice)
	%% permute
	%
	% sous-fonction pour permuter les deux valeurs consécutives d'un vecteur
	tmp = V(indice);
	V(indice) = V(indice+1);
	V(indice+1) = tmp;
	tri = true;
end

trier_c, trier_d et permute sont des fonctions locales. Elles ne sont utilisables que dans le contexte de la fonction tribulle.

Remarque

L'ordre des fonctions n'a aucune importance. Les sous-fonctions et la fonction principale peuvent être définies dans n'importe quel ordre, du moment qu'elles sont effectivement dans le même fichier.

Remarque

On peut accéder à l'aide des sous-fonctions grâce à l'opérateur > :

>> help tribulle>permute
 
permute
 
sous-fonction pour permuter les deux valeurs consécutives d'un vecteur

Remarque

Il existe une fonction prédéfinie qui s'appelle aussi permute, cette fonction ne fait pas du tout la même chose que notre fonction locale : la fonction prédéfinie est une fonction qui permute les dimensions des tableaux, c'est une généralisation de la transposition.

Par définition, les fonctions locales n'ont une existence qu'au sein de la fonction principale. Le fait que l'on définisse une fonction locale ayant un nom identique à une fonction pré-existante ne pose aucun problème, parce que l'on n'a pas besoin de la fonction permute pré-définie !

La fonction locale est toujours prioritaire par rapport à une fonction externe, pré-définie ou non, ayant le même nom.

Fonction imbriquée

Les fonctions imbriquées sont un autre type de sous-fonctions.

Syntaxe

Une fonction imbriquée est un bloc fonctionnel contenu dans un autre bloc fonctionnel, correspondant à une fonction ou une fonction locale :

function [s_1 ... s_ns] = maFonction(e_1... e_ne)
    instructions ;
   
    function [s_1 ... s_ls] = uneFonctionImbriquee(e_1... e_le)
        instructions ;
    end
   
end
 
function [s_1 ... s_ms] = uneFonctionLocale(e_1... e_me)
    instructions ;
   
    function [s_1 ... s_ps] = uneAutreFonctionImbriquee(e_1... e_pe)
        instructions ;
    end
   
end
 

Exemple

Nous avons ré-écrit l'exemple tribulle, en utilisant maintenant des fonctions imbriquées. Dans cette nouvelle version, la fonction tribulle_versionImbriquee contient une sous-fonction imbriquée trier, qui elle-même contient une sous-fonction imbriquée permute :

%% tribulle_versionImbriquee.m
% Fabien Baillon et Jean-Louis Dirion - Novembre 2014
%
% Cette fonction permet de trier un ensemble de valeurs.
% V est le vecteur de valeurs à trier.
%
% ordre est un caractère :
%       s'il vaut 'c', le tri sera par ordre croissant,
%       s'il vaut 'd', le tri sera par ordre décroissant.
%
% La méthode utilisée pour ordonner le vecteur V est le tri par bulle.

function V = tribulle_versionImbriquee(V,ordre)

    continu = true;

    while(continu)
        trier();
    end

    
    function [] = trier()
	%% trier
	%
	% sous-fonction pour le tri
    
        continu = false;
        for indice=1:length(V)-1
            switch ordre
                case 'c'
                    if(V(indice) > V(indice+1)) permute(); end
                case 'd'
                    if(V(indice) < V(indice+1)) permute(); end
            end
        end
    
    
        function [] = permute()
		%% permute
		%
		% sous-fonction pour permuter les deux valeurs consécutives d'un vecteur
            tmp = V(indice);
            V(indice) = V(indice+1);
            V(indice+1) = tmp;
            continu = true;
        end

    end

end
    
 
   

Remarque

Les fonctions sont imbriquées, de ce fait les sous-fonctions ont accès aux variables définies dans la fonction ou la sous-fonction qui les englobe.

C'est pourquoi les variables ne sont plus passées en argument des sous-fonctions, car ce n'est pas nécessaire ici. Contrairement aux fonctions locales, les fonctions imbriquées partagent le même espace mémoire (workspace).

Remarque

Les sous-fonctions n'ont pas de variables d'entrée et de sortie, car ici, ce n'est plus nécessaire. De ce fait, on aurait pu ne pas indiquer de vecteur de sortie, et ne pas mettre de parenthèses, lors de la définition des sous-fonctions, en écrivant par exemple :

function trier

Cependant, nous préférons les mettre malgré tout, pour indiquer explicitement qu'il n'y a pas d'entrée et de sortie (ce n'est pas un oubli !) :

function [] = trier()