La présentation est en train de télécharger. S'il vous plaît, attendez

La présentation est en train de télécharger. S'il vous plaît, attendez

Chapitre 9 Les sous-programmes.

Présentations similaires


Présentation au sujet: "Chapitre 9 Les sous-programmes."— Transcription de la présentation:

1 Chapitre 9 Les sous-programmes

2 Chapitre 9: Sujets Introduction Éléments de base des sous-programmes
Choix de conception Environnement référentiel local Méthodes de passage des paramètres Passage de sous-programme en paramètre Surcharge des sous-programmes Sous-programmes génériques Choix de conception pour les fonctions Surcharge des opérateurs définie par l'usager Coroutines 2

3 Introduction Deux types fondamentaux d'abstraction
Abstraction des processus Présent dès le début du développement de l'informatique Exemple: trier(liste, longueur) Abstraction des données Surtout depuis les années 80 Données + opérations Exemples: Pile, dictionnaire, etc.

4 Éléments de base des sous-programmes
Chaque sous-programme a un unique point d'entrée La routine appelante est suspendue pendant l'exécution d'un sous-programme Le contrôle retourne à la routine appelante lorsque l'exécution du sous-programme est terminée. Exception en Perl: goto &fct La fonction appelante est enlevée de la pile d'appel.

5 Définitions élémentaires
La définition d'un sous-programme décrit l'interface ainsi que les actions effectuées par la sous-routine. Un appel de sous-programme est une instruction qui demande explicitement d'exécuter un sous-programme. Une en-tête est la première partie de la définition: cela inclu: le nom la sorte de sous-programme (fonction ou procédure) les paramètres formels le type de la valeur de retour dans le cas d'une fonction

6 Procédures et fonctions
Il existe deux catégories de sous- programmes: Procédures: collection d'instructions définissant un calcul paramétrisé. Fonctions: Structurellement similaires aux procédures mais retournent une valeur En l'absence d'effet de bord, les fonctions d'un langage de programmation correspondent aux fonctions mathématiques.

7 Paramètres formels et effectifs
Un paramètre formel est une variable apparaissant dans la liste des paramètres et utilisée dans le sous-programme. Un paramètre d'appel (ou effectif ) est une valeur ou adresse utilisée comme paramètre dans l'appel d'un sous- programme

8 Paramètres formels et effectifs (suite)
La correspondance entre les paramètres d'appel et les paramètres formels peut se faire de deux façons: Selon la position des paramètres Sur et efficace Par association explicite Le nom du paramètre formel auquel correspond un paramètre effectif est spécifié lors de l'appel. Les paramètres peuvent apparaître dans n'importe quel ordre. Ada, Fortran et Python utilisent cette méthode en plus de la méthode positionnelle.

9 Paramètres formels et effectifs (suite)
Exemple en Python: >>> def f(a,b): return a-b >>> f(1,6) -4 >>> f(b=1,a=6) 5 >>>

10 Valeur de défaut des paramètres formels
Dans certains langages (e.g. C++, Ada et Python) on peut donner une valeur de défaut aux paramètres formels Python: >>> def f(x=1,y=1,z=1): print x, y, z ... >>> f(y=2) 1 2 1 En C les fonctions (en C# les méthodes) peuvent accepter un nombre variable de paramètres

11 Exemple en C Affiche: 10 20 21 #include <stdio.h>
#include <stdarg.h> int f(int n, ...){ int i; va_list pa; va_start(pa,n); for (i=0;i<n;i++) printf("%d ", va_arg(pa, int)); printf("\n"); } int main(){ f(1,10); f(2,20,21); Affiche: 10 20 21

12 Choix de conception Quelles méthodes de passage des paramètres sont disponibles? Y a-t-il vérification du type des paramètres? Les variables locales sont-elles statiques ou dynamiques? Peut-on définir des sous-programmes à l'intérieur d'autres sous-programmes? Les sous-programmes peuvent-ils être surchargés? Les sous-programmes peuvent-ils être génériques?

13 Environnement local Les variables locales peuvent être dynamique sur pile: Avantages Permet la récursion Partage de la mémoire Désavantages Temps d'initialisation Adressage indirect Les sous-programmes n'ont pas de mémoire cela peut être vu comme un avantage: réduit les effets de bord Les variables locales peuvent être statiques: Plus efficace (pas d'indirection) Pas besoin d'initialiser la pile Ne supporte pas la récursion En Fortran 95, on utilise le mot clef Recursive pour indiquer qu'une fonction peut être récursive

14 Méthodes de passage des paramètres
Façon avec laquelle les paramètres sont transmis et récupérés lors d'un appel de sous-programme: Par valeur Par résultat Par copie Par par référence Par par nom

15 Modélisation

16 Passage par valeur (lecture seulement)
La valeur du paramètre d'appel est utilisée pour initialiser le paramètre formel correspondant Espace supplémentaire requis Opération de copie couteuse

17 Passage par résultat (écriture seulement)
Aucune valeur n'est transmise au sous- programme. Le paramètre formel correspondant est utilisé comme variable locale servant à transmettre au programme appelant la valeur calculée par le sous-programme Requiert de l'espace supplémentaire ainsi qu'une opération de copie Problème potentiel: sub(p1, p1): Lequel des 2 valeurs de retour est copiée dans p1?

18 Passage par copie Combine les deux types de passages précédents
Les paramètres formels ont un espace de stockage local Désavantages: Les mêmes que les deux modes précédents

19 Passage par référence Un chemin d'accès est transmis Avantages:
Efficace: pas de copie et pas d'espace dupliqué) Désavantages Accès plus lent (comparé au passage par copie) Effets de bord potentiel Création de pseudonymes (alias)

20 Passage par nom Substitution textuelle du paramètre:
int f(int x){return x*x*x;} Un appel à f(a+2*b) devient: return (a+2*b)*(a+2*b)*(a+2*b) Utilisé dans Algol 60

21 Exemple: copie vs référence
int G=3; /*variable globale*/ void fct(int a, int b){G=b;} void main{ int Liste[10]; Liste[G]=5; fct(G, Liste[G]) } Valeur de G au retour de fct: Par copie: G vaut 3 Par référence: G vaut 5 Passage par copie: adr_G = &G adr_LG = &liste[G] a = *adr_G b = *adr_LG G = b *adr_G = a *adr_LG = b

22 Choix de conception pour le passage de paramètres
Deux considérations Efficacité Transfert unidirectionel ou bidirectionnel En théorie: Toujours privilégier le transfert unidirectionnel En pratique: Passage par référence plus efficace pour de grosses structures comme les tableaux.

23 Implémentation du passage de paramètres
Dans la plupart des langages les paramètres sont passés via la pile Le passage par référence est le plus simple: seule l'adresse est mise sur la pile. On doit faire attention à l'implémentation du passage par référence et par copie lorsque les paramètres d'appel sont des constantes

24 Passage de paramètres dans certains langages
Passage par valeur Passage par référence effectué en utilisant les pointeurs C++ Un type de pointeur spécial appelé référence est utilisé pour effectuer le passage par référence. Java Tous les paramètres sont passés par valeur sauf les objets qui eux sont passés par référence C# Par défaut: passage par valeur Passage par référence: on met le mot clef ref avant les paramètre formel et effectif

25 Passage de paramètres dans certains langages (suite)
Ada Trois modes de transmission: in, out et in out; par défaut on utilise in Les paramètres in out sont passés par copie Fortran Similaire à Ada PHP: similaire à C# Perl: Le paramètres sont transmis via le tableau @_

26 Vérification du type des paramètres
Très important pour la fiabilité Aucune vérification en FORTRAN 77 et en C original Pascal, FORTRAN 90, Java, et Ada: Toujours Perl, JavaScript, Python, Ruby et PHP: Pas de vérification

27 Vérification du type des paramètres
C 72: Pas de vérification double sin() double x; { ... } C 89: L'usager a le choix entre la version précédente et la suivante (type vérifié): double sin(double x) C99 et C++: Type (presque) toujours vérifié

28 Exemple en C99 et C++ #include <stdio.h>
#include <stdarg.h> int f(int p, ...){ // Le type des autres paramètres // n'est pas vérifié va_list pa; va_start(pa, p); /* Pointe return va_arg(pa, int); } int main(){ float x=3.1216; int n; n=f(1, x); printf("%d\n", n);

29 Tableaux multidimensionnels
Le sous-programme doit connaître la taille des tableaux pour calculer la fonction d'accès. C'est le cas, en particulier, lorsque le sous- programme est compilé dans un autre module que celui où est défini le tableau.

30 Tableaux multidimensionnels: C et C++
La taille de toutes les dimensions (sauf la première) doit être fournie: void fct(int mat[][100]) ... Enlève de la flexibilité Solution: Utilisation des pointeurs

31 Tableaux multidimensionnels: Ada
with Text_Io; use text_Io; procedure Main is type Mat_Type is array (Integer range <>, Integer range <>) of Integer; M : Mat_Type(1..2, 1..2):=((1,2),(3,4)); T : Integer; function Somme(Mat : in Mat_Type) return Integer is S : Integer; begin S := 0; for i in Mat'range(1) loop for j in Mat'range(2) loop S := S + Mat(i,j); end loop; return S; end Somme; T := Somme(M); put_line("La somme est " & Integer'Image(T)); end Main;

32 Tableaux multidimensionnels: Fortran
Les paramètres formels qui sont des tableaux ont une déclaration après l'en- tête: Subroutine Sub(M, i, j, Resultat) Integer, Intent(In) :: i, j Real, Dimension(i,j), Intent(In) :: M Real, Intent(Out) :: Result ... End Subroutine Sub

33 Tableaux multidimensionnels: Java et C#
Similaire à Ada Chaque tableau possède un attribut (length en Java, Length en C#) défini lors de la création S = 0; for (int i=0; i<Mat.length); i++) for (int j=0; j<Mat[i].length; j++) S += Mat[i][j]; Remarque: Mat est un tableau de tableaux.

34 Passer un sous-programme en paramètre
Choix de conception: Le type des paramètres est-il vérifié? Quel est l'environnement de référence utilisé?

35 Passer un sous-programme en paramètre: vérification de type
C et C++: on ne peux passer qu'un pointeur de fonction et non pas la fonction elle même; le type des paramètres est vérifié FORTRAN 95: Type vérifié Pascal et Ada ne permettent pas de passer des sous-programmes en paramètre; En Ada on utilise plutôt les sous-programmes génériques

36 Passer un sous-programme en paramètre: Environnement
Liaison superficielle (dynamique): L'environnement où est exécuté le sous- programme Liaison profonde (statique): L'environnement où est défini le sous- programme Liaison ad-hoc (jamais utilisé): L'environnement où le sous-programme est passé en paramètre

37 Exemple en JavaScript Superficielle: x=4 Profonde: x=1 Ad-hoc: x=3
function sub1(){ var x; function sub2(){ alert(x); }; // ouvre une boite de dialogue function sub3(){ x=3; sub4(sub2); }; function sub4(subx){ x=4; subx(); }; x=1; sub3(); }; Superficielle: x=4 Profonde: x=1 Ad-hoc: x=3

38 Surcharge des sous-programmes
Plusieurs sous-programmes avec le même nom Chaque version possède un prototype exclusif. Ada, Java, C++, et C# permettent à l'usager de surcharger ses propres sous-programmes En Ada, le type de retour d'une fonction est utilisé pour discréminer les fonctions surchargées (donc deux fonctions surchargées peuvent avoir les mêmes paramètres)

39 Sous-programmes génériques
Un sous-programme est générique (ou polymorphique) s'il peut être exécuté avec différents types de paramètres. Christopher Strachey a défini en 1967 deux types de polymorphismes: Polymorphisme ad hoc : Dans le cas des sous-programmes surchargés Nombre fini de situations définies explicitement Polymorphisme paramétrique: Dans le cas des sous-programmes dont le type des paramètres est générique. Le sous-programme peut être utilisé avec un nombre illimité de nouveaux types.

40 Exemple en C++ template <class Type>
Type max(Type first, Type second) { return first > second ? first : second; } On peut utiliser la fonction précédente avec n'importe quel type pour lequel l'opérateur > est défini. int a,b,c; float x,y,z; ... c = max(a,b); z = max(x,y);

41 Exemple en C++ Un template peut aussi avoir une valeur de défaut
template <class Type> struct greater { bool operator()(Type a, Type b){return a>b;} }; template <class Type, class comp=greater<Type> > Type max(Type x, Type y) { comp plusgrand; return plusgrand(x,y) ? x : y; }

42 Exemple: Ada Algorithme de tri generic type Index_Type is (<>);
type Element_Type is private; type Vector is array(Index_Type range <>) of Element_Type; with function ">"(Left, Right: Element_Type) return BOOLEAN is <>; procedure Generic_Sort(List: in out Vector);

43 Exemple: Ada (suite) procedure Generic_Sort(List: in out Vector) is
Temp: Element_Type; begin for Top in List'First..Index_Type'Pred(List'Last) loop for Bottom in Index_Type'Succ(Top)..List'Last loop if List(Top) > List(Bottom) then Temp:=List(Top); List(Top):=List(Bottom); List(Bottom):=Temp; end if; end loop; end Generic_Sort;

44 Exemple: Ada (suite) type Int_Array is array (INTEGER range <>) of INTEGER; procedure Integer_Sort is new Generic_Sort( Index_type=>INTEGER, Element_Type=>INTEGER, Vector=>Int_Array);

45 Exemple: Java Principale différence entre Java et C++ (ou Ada):
Les paramètres génériques doivent être des classes Une seule copie du code est construite: elle opère sur la classe Object Des restrictions peuvent être mises sur les types pouvant être utilisés comme paramètre

46 Exemple: Java public class compare {
public static <E extends Comparable> E min(E[] tab){ E pluspetit = tab[0]; for (int i=1; i<tab.length; i++) if (tab[i].compareTo(pluspetit) < 0) pluspetit = tab[i]; return pluspetit;} public static void main(String[] arg){ String[] S={"Ferron", "Ducharme", "Tremblay"}; System.out.println(min(S)); Integer[] I={7, 2, 13, 45, 1, 43}; System.out.println(min(I)); }

47 Considérations particulières pour les fonctions
Les effets de bord sont ils permis? Les paramètres devraient toujours être unidirectionnel pour prévenir les effets de bord (comme Ada) Quels sont les types permis pour la valeur de retour? La plupart des langages impératifs restreignent le type de retour C permet n'importe quel type sauf les tableaux et les fonctions C++ est comme C et permet de retourner des classes Ada permet n'importe quel type Les méthodes de Java et C# permettent n'importe quel type

48 Opérateurs surchargé par l'usager
Les opérateurs peuvent être surchargés en Ada, C#, Perl, Python et C++ Cela n'est pas possible en C, Java, JavaScript et PHP. Exemple en Ada: Function “*”(A,B: in Vecteur): return Integer is Sum: Integer := 0; begin for Index in A’range loop Sum := Sum + A(Index) * B(Index) end loop return sum; end “*”; ... a,b,c : Vecteur; c = a * b;

49 Définition de nouveaux opérateurs
Certain langages permettent de définir et surcharger de nouveaux opérateurs: e.g. Algol, Fortran, Lisp, Prolog, Perl et Haskell

50 Coroutines Une coroutine est une généralisation des sous- programmes
Plusieurs points d'entrées contrôlés par les coroutines elles-mêmes Il n'y a pas de relation maître-esclave entre les coroutines Une coroutine est appelée à l'aide d'une instruction telle que resume Analogue à l'exécution de plusieurs threads sauf qu'ici les coroutines gèrent elles-mêmes l'ordonnancement.

51 Coroutines (suite) Lors du premier resume la coroutine commence au début du code comme un sous-programme normal Lors des appels subséquents, la coroutine poursuit son exécution au point où elle était rendu avant sa dernière interruption Une interruption se produit lorsqu'une coroutine appelle une autre coroutine. Origine: article de Melvin Conway (1963) Présent dans Simula 67, Modula-2, Python, Lua et quelques autres langages.

52 Illustration des coroutines: 2 coroutines sans boucles

53 Illustration des coroutines: 2 coroutines avec boucles

54 Les générateurs Mécanisme permettant de construire facilement des itérateurs Généralisation des fonctions Plusieurs points d'entrées Peut retourner une valeur plusieurs fois en cours d'exécution Les générateurs sont aux fonctions ce que les coroutines sont aux procédures. Première apparition: CLU (MIT 1975) Aussi dans Python, C#, et d'autres

55 Exemple en Lua for i=1,10 do print("co", i) coroutine.yield() end end)
co = coroutine.create(function () for i=1,10 do print("co", i) coroutine.yield() end end) coroutine.resume(co) --> co 1 coroutine.resume(co) --> co 2 coroutine.resume(co) --> co 3 ... coroutine.resume(co) --> co 10 coroutine.resume(co) n'affiche rien

56 Les générateurs en Python
>>> def fib(): a,b = 0,1 while 1: yield b a,b = b, a+b >>> g=fib() >>> g.next() 1 2 3 5 >>>

57 Les itérateurs en Python
>>> for i in [0,1,2,3,4,5,6,7,8,9]: if i>100: break print i >>> for i in range(10): >>> a = ['Un', 'petit', 'exemple'] >>> for i in range(len(a)): print i, a[i]

58 Générateurs et itérateurs en Python
>>> for i in fib(): if i>100: break print i 1 2 3 5 8 13 21 34 55 89 >>>

59 Exemple en Python >>> class Reverse:
"Itérateur pour parcourir une liste à l'envers" def __init__(self, data): self.data = data self.index = len(data) def __iter__(self): return self def next(self): if self.index == 0: raise StopIteration self.index = self.index - 1 return self.data[self.index] ... >>> for c in Reverse('spam'): print c

60 Sommaire La définition d'un sous-programme décrit les actions effectuées Un sous-programme peut être une fonction ou une procédure Les variables locales peuvent être dynamiques sur pile ou statiques Il y a trois principaux modèles de passage de paramètres: lecture, écriture et bidirectionnel Certains langages permettent la surcharge des opérateurs et des sous-programmes Les sous-programme peuvent être génériques Les coroutines et les générateurs sont des généralisations des sous-programmes.


Télécharger ppt "Chapitre 9 Les sous-programmes."

Présentations similaires


Annonces Google