58
ISBN 0-321-49362-1 Chapitre 9 Les sous-programmes

ISBN 0-321-49362-1 Chapitre 9 Les sous-programmes

Embed Size (px)

Citation preview

Page 1: ISBN 0-321-49362-1 Chapitre 9 Les sous-programmes

ISBN 0-321-49362-1

Chapitre 9

Les sous-programmes

Page 2: ISBN 0-321-49362-1 Chapitre 9 Les sous-programmes

1-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

Page 3: ISBN 0-321-49362-1 Chapitre 9 Les sous-programmes

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

Page 4: ISBN 0-321-49362-1 Chapitre 9 Les sous-programmes

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

Page 5: ISBN 0-321-49362-1 Chapitre 9 Les sous-programmes

1-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

Page 6: ISBN 0-321-49362-1 Chapitre 9 Les sous-programmes

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

Page 7: ISBN 0-321-49362-1 Chapitre 9 Les sous-programmes

1-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

Page 8: ISBN 0-321-49362-1 Chapitre 9 Les sous-programmes

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

Page 9: ISBN 0-321-49362-1 Chapitre 9 Les sous-programmes

1-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

>>>

Page 10: ISBN 0-321-49362-1 Chapitre 9 Les sous-programmes

1-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

Page 11: ISBN 0-321-49362-1 Chapitre 9 Les sous-programmes

1-11

Exemple en C#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:1020 21

Page 12: ISBN 0-321-49362-1 Chapitre 9 Les sous-programmes

1-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?

Page 13: ISBN 0-321-49362-1 Chapitre 9 Les sous-programmes

1-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

Page 14: ISBN 0-321-49362-1 Chapitre 9 Les sous-programmes

1-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

Page 15: ISBN 0-321-49362-1 Chapitre 9 Les sous-programmes

1-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

Page 16: ISBN 0-321-49362-1 Chapitre 9 Les sous-programmes

1-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?

Page 17: ISBN 0-321-49362-1 Chapitre 9 Les sous-programmes

1-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

Page 18: ISBN 0-321-49362-1 Chapitre 9 Les sous-programmes

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

Page 19: ISBN 0-321-49362-1 Chapitre 9 Les sous-programmes

1-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

Page 20: ISBN 0-321-49362-1 Chapitre 9 Les sous-programmes

1-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

Page 21: ISBN 0-321-49362-1 Chapitre 9 Les sous-programmes

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

Page 22: ISBN 0-321-49362-1 Chapitre 9 Les sous-programmes

1-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

Page 23: ISBN 0-321-49362-1 Chapitre 9 Les sous-programmes

1-24

Passage de paramètres dans certains langages• C

– 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

Page 24: ISBN 0-321-49362-1 Chapitre 9 Les sous-programmes

1-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 @_

Page 25: ISBN 0-321-49362-1 Chapitre 9 Les sous-programmes

1-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

Page 26: ISBN 0-321-49362-1 Chapitre 9 Les sous-programmes

1-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é

Page 27: ISBN 0-321-49362-1 Chapitre 9 Les sous-programmes

1-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);}

Page 28: ISBN 0-321-49362-1 Chapitre 9 Les sous-programmes

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

Page 29: ISBN 0-321-49362-1 Chapitre 9 Les sous-programmes

1-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

Page 30: ISBN 0-321-49362-1 Chapitre 9 Les sous-programmes

1-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; end loop; return S; end Somme;

begin T := Somme(M); put_line("La somme est " & Integer'Image(T)); end Main;

Page 31: ISBN 0-321-49362-1 Chapitre 9 Les sous-programmes

1-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, jReal, Dimension(i,j), Intent(In) :: MReal, Intent(Out) :: Result...

End Subroutine Sub

Page 32: ISBN 0-321-49362-1 Chapitre 9 Les sous-programmes

1-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éationS = 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.

Page 33: ISBN 0-321-49362-1 Chapitre 9 Les sous-programmes

1-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é?

Page 34: ISBN 0-321-49362-1 Chapitre 9 Les sous-programmes

1-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

Page 35: ISBN 0-321-49362-1 Chapitre 9 Les sous-programmes

1-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

Page 36: ISBN 0-321-49362-1 Chapitre 9 Les sous-programmes

1-37

Exemple en JavaScript

function sub1(){var x;function sub2(){

alert(x); }; // ouvre une boite de dialoguefunction sub3(){

var x;x=3;sub4(sub2); };

function sub4(subx){var x;x=4;subx(); };

x=1;sub3(); };

Superficielle: x=4Profonde: x=1Ad-hoc: x=3

Page 37: ISBN 0-321-49362-1 Chapitre 9 Les sous-programmes

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

Page 38: ISBN 0-321-49362-1 Chapitre 9 Les sous-programmes

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

Page 39: ISBN 0-321-49362-1 Chapitre 9 Les sous-programmes

1-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);

Page 40: ISBN 0-321-49362-1 Chapitre 9 Les sous-programmes

1-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;

}

Page 41: ISBN 0-321-49362-1 Chapitre 9 Les sous-programmes

1-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);

Page 42: ISBN 0-321-49362-1 Chapitre 9 Les sous-programmes

1-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 loop;end Generic_Sort;

Page 43: ISBN 0-321-49362-1 Chapitre 9 Les sous-programmes

1-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);

Page 44: ISBN 0-321-49362-1 Chapitre 9 Les sous-programmes

1-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

Page 45: ISBN 0-321-49362-1 Chapitre 9 Les sous-programmes

1-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)); } }

Page 46: ISBN 0-321-49362-1 Chapitre 9 Les sous-programmes

1-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;

Page 47: ISBN 0-321-49362-1 Chapitre 9 Les sous-programmes

1-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

Page 48: ISBN 0-321-49362-1 Chapitre 9 Les sous-programmes

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

Page 49: ISBN 0-321-49362-1 Chapitre 9 Les sous-programmes

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

Page 50: ISBN 0-321-49362-1 Chapitre 9 Les sous-programmes

1-52

Illustration des coroutines:2 coroutines sans boucles

Page 51: ISBN 0-321-49362-1 Chapitre 9 Les sous-programmes

1-53

Illustration des coroutines:2 coroutines avec boucles

Page 52: ISBN 0-321-49362-1 Chapitre 9 Les sous-programmes

1-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

Page 53: ISBN 0-321-49362-1 Chapitre 9 Les sous-programmes

1-55

Exemple en Lua

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

Page 54: ISBN 0-321-49362-1 Chapitre 9 Les sous-programmes

1-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>>> g.next()1>>> g.next()2>>> g.next()3>>> g.next()5>>>

Page 55: ISBN 0-321-49362-1 Chapitre 9 Les sous-programmes

1-57

Les itérateurs en Python

>>> for i in [0,1,2,3,4,5,6,7,8,9]:if i>100: breakprint i

>>> for i in range(10):if i>100: breakprint i

>>> a = ['Un', 'petit', 'exemple'] >>> for i in range(len(a)): print i, a[i]

Page 56: ISBN 0-321-49362-1 Chapitre 9 Les sous-programmes

1-58

Générateurs et itérateurs en Python>>> for i in fib():

if i>100: breakprint i

1123581321345589>>>

Page 57: ISBN 0-321-49362-1 Chapitre 9 Les sous-programmes

1-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

Page 58: ISBN 0-321-49362-1 Chapitre 9 Les sous-programmes

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