Paramètre (programmation informatique) - Parameter (computer programming)

En programmation informatique , un paramètre ou un argument formel est un type spécial de variable utilisé dans un sous - programme pour faire référence à l'une des données fournies en entrée du sous-programme. Ces données sont les valeurs des arguments (souvent appelés arguments réels ou paramètres réels ) avec lesquels le sous-programme va être appelé/invoqué. Une liste ordonnée de paramètres est généralement incluse dans la définition d'un sous-programme , de sorte que, chaque fois que le sous-programme est appelé, ses arguments pour cet appel sont évalués et les valeurs résultantes peuvent être affectées aux paramètres correspondants.

Contrairement à l' argument dans l'usage mathématique habituel, l' argument en informatique est l'expression d'entrée réelle transmise/fournie à une fonction, une procédure ou une routine dans l'instruction d'invocation/appel, tandis que le paramètre est la variable à l'intérieur de l'implémentation de la sous-routine. Par exemple, si l'on définit le addsous - programme comme def add(x, y): return x + y, alors x, ysont les paramètres, tandis que s'il est appelé comme add(2, 3), alors 2, 3sont les arguments. Notez que les variables (et leurs expressions) du contexte appelant peuvent être des arguments : si le sous-programme est appelé comme, a = 2; b = 3; add(a, b)les variables a, b sont les arguments, pas les valeurs 2, 3 . Voir la section Paramètres et arguments pour plus d'informations.

La sémantique sur la façon dont les paramètres peuvent être déclarés et la façon dont les (valeurs des) arguments sont passés aux paramètres des sous-routines sont définies par la stratégie d'évaluation du langage, et les détails de la façon dont cela est représenté dans un système informatique particulier dépendent de l' appel. convention de ce système. Dans le cas le plus courant, appel par valeur , un paramètre agit dans le sous-programme comme une nouvelle variable locale initialisée à la valeur de l'argument (une copie locale (isolée) de l'argument si l'argument est une variable), mais dans d'autres cas , par exemple appel par référence , la variable d'argument fournie par l'appelant peut être affectée par des actions au sein du sous-programme appelé.

Exemple

Le programme suivant dans le langage de programmation C définit une fonction nommée "SalesTax" et possède un paramètre nommé "price". Le type de prix est "double" (c'est -à- dire un nombre à virgule flottante double précision ). Le type de retour de la fonction est également un double.

double SalesTax(double price)
{
  return 0.05 * price;
}

Une fois la fonction définie, elle peut être appelée comme suit :

SalesTax(10.00);

Dans cet exemple, la fonction a été appelée avec l' argument 10.00. Lorsque cela se produit, 10,00 seront attribués au prix et la fonction commencera à calculer son résultat. Les étapes de production du résultat sont précisées ci-dessous, entre {}. 0.05 * priceindique que la première chose à faire est de multiplier 0,05 par la valeur du prix, ce qui donne 0,50. returnsignifie que la fonction produira le résultat de 0.05 * price. Par conséquent, le résultat final (en ignorant les éventuelles erreurs d'arrondi que l'on rencontre en représentant les fractions décimales sous forme de fractions binaires) est de 0,50.

Paramètres et arguments

Les termes paramètre et argument peuvent avoir des significations différentes dans différents langages de programmation. Parfois, ils sont utilisés de manière interchangeable, et le contexte est utilisé pour distinguer le sens. Le terme paramètre (parfois appelé paramètre formel ) est souvent utilisé pour désigner la variable telle qu'elle se trouve dans la définition de la fonction, tandis que l' argument (parfois appelé paramètre réel ) fait référence à l'entrée réelle fournie lors de l'appel de la fonction. Par exemple, si l'on définit une fonction comme def f(x): ..., alors xest le paramètre, et si elle est appelée par a = ...; f(a)alors aest l'argument. Un paramètre est une variable (non liée), tandis que l'argument peut être un littéral ou une variable ou une expression plus complexe impliquant des littéraux et des variables. En cas d'appel par valeur, ce qui est passé à la fonction est la valeur de l'argument - par exemple, f(2)et a = 2; f(a)sont des appels équivalents - tandis que dans l'appel par référence, avec une variable comme argument, ce qui est passé est une référence à cette variable - même si la syntaxe de l'appel de fonction peut rester la même. La spécification du passage par référence ou du passage par valeur serait faite dans la déclaration et/ou la définition de la fonction.

Les paramètres apparaissent dans les définitions de procédure ; les arguments apparaissent dans les appels de procédure. Dans la définition de la fonction, f(x) = x*xla variable x est un paramètre ; dans l'appel de fonction, f(2)la valeur 2 est l'argument de la fonction. En gros, un paramètre est un type et un argument est une instance.

Un paramètre est une propriété intrinsèque de la procédure, incluse dans sa définition. Par exemple, dans de nombreuses langues, une procédure pour additionner deux entiers fournis et calculer la somme aurait besoin de deux paramètres, un pour chaque entier. En général, une procédure peut être définie avec un nombre quelconque de paramètres, ou aucun paramètre du tout. Si une procédure a des paramètres, la partie de sa définition qui spécifie les paramètres est appelée sa liste de paramètres .

En revanche, les arguments sont les expressions fournies à la procédure lorsqu'elle est appelée, généralement une expression correspondant à l'un des paramètres. Contrairement aux paramètres, qui font partie intégrante de la définition de la procédure, les arguments peuvent varier d'un appel à l'autre. Chaque fois qu'une procédure est appelée, la partie de l'appel de procédure qui spécifie les arguments est appelée la liste d'arguments .

Bien que les paramètres soient également communément appelés arguments, les arguments sont parfois considérés comme les valeurs réelles ou les références affectées aux variables de paramètre lorsque le sous-programme est appelé au moment de l' exécution . Lorsque vous discutez du code qui appelle un sous-programme, toutes les valeurs ou références passées dans le sous-programme sont les arguments, et l'endroit dans le code où ces valeurs ou références sont données est la liste de paramètres . Lors de la discussion du code à l'intérieur de la définition du sous-programme, les variables dans la liste des paramètres du sous-programme sont les paramètres, tandis que les valeurs des paramètres à l'exécution sont les arguments. Par exemple, en C, lorsqu'il s'agit de threads, il est courant de passer un argument de type void* et de le transtyper en un type attendu :

void ThreadFunction(void* pThreadArgument)
{
  // Naming the first parameter 'pThreadArgument' is correct, rather than
  // 'pThreadParameter'. At run time the value we use is an argument. As
  // mentioned above, reserve the term parameter for when discussing
  // subroutine definitions.
}

Pour mieux comprendre la différence, considérons la fonction suivante écrite en C :

int Sum(int addend1, int addend2)
{
  return addend1 + addend2;
}

La fonction Sum a deux paramètres, nommés addend1 et addend2 . Il ajoute les valeurs passées dans les paramètres, et renvoie le résultat à l'appelant du sous-programme (en utilisant une technique fournie automatiquement par le compilateur C).

Le code qui appelle la fonction Sum pourrait ressembler à ceci :

int value1 = 40;
int value2 = 2;
int sum_value = Sum(value1, value2);

Les variables valeur1 et valeur2 sont initialisées avec des valeurs. valeur1 et valeur2 sont tous deux des arguments de la fonction sum dans ce contexte.

Lors de l'exécution, les valeurs affectées à ces variables sont transmises à la fonction Somme en tant qu'arguments. Dans la fonction Sum , les paramètres addend1 et addend2 sont évalués, donnant respectivement les arguments 40 et 2. Les valeurs des arguments sont ajoutées et le résultat est renvoyé à l'appelant, où il est affecté à la variable sum_value .

En raison de la différence entre les paramètres et les arguments, il est possible de fournir des arguments inappropriés à une procédure. L'appel peut fournir trop ou trop peu d'arguments ; un ou plusieurs des arguments peuvent être d'un type incorrect ; ou les arguments peuvent être fournis dans le mauvais ordre. Chacune de ces situations provoque une incompatibilité entre les listes de paramètres et d'arguments, et la procédure renvoie souvent une réponse inattendue ou génère une erreur d'exécution .

Convention alternative à Eiffel

Dans la méthode et le langage de développement logiciel Eiffel , les termes argument et paramètre ont des usages distincts établis par convention. Le terme argument est utilisé exclusivement en référence aux entrées d'une routine, et le terme paramètre est utilisé exclusivement dans le paramétrage de type pour les classes génériques .

Considérez la définition de routine suivante :

    sum (addend1: INTEGER; addend2: INTEGER): INTEGER
        do
            Result := addend1 + addend2
        end

La routine sumprend deux arguments addend1et addend2, qui sont appelés les arguments formels de la routine . Un appel à sumspécifie les arguments réels , comme indiqué ci-dessous avec value1et value2.

    sum_value: INTEGER
    value1: INTEGER = 40
    value2: INTEGER = 2
                
            sum_value := sum (value1, value2)

Les paramètres sont également considérés comme formels ou réels . Les paramètres génériques formels sont utilisés dans la définition des classes génériques. Dans l'exemple ci-dessous, la classe HASH_TABLE est déclarée comme une classe générique qui a deux paramètres génériques formels, Greprésentant les données d'intérêt et Kreprésentant la clé de hachage pour les données :

class HASH_TABLE [G, K -> HASHABLE] 
            

Lorsqu'une classe devient un client de HASH_TABLE, les paramètres génériques formels sont remplacés par des paramètres génériques réels dans une dérivation générique . Dans la déclaration d'attribut suivante, my_dictionarydoit être utilisé comme un dictionnaire basé sur une chaîne de caractères . En tant que tels, les données et les paramètres génériques formels clés sont remplacés par des paramètres génériques réels de type STRING.

    my_dictionary: HASH_TABLE [STRING, STRING]

Types de données

Dans les langages de programmation fortement typés , le type de chaque paramètre doit être spécifié dans la déclaration de procédure. Les langages utilisant l' inférence de type tentent de découvrir les types automatiquement à partir du corps et de l'utilisation de la fonction. Les langages de programmation à typage dynamique reportent la résolution de type jusqu'à l'exécution. Les langages faiblement typés effectuent peu ou pas de résolution de type, s'appuyant plutôt sur le programmeur pour l'exactitude.

Certains langages utilisent un mot-clé spécial (par exemple void ) pour indiquer que le sous-programme n'a pas de paramètres ; en théorie des types formels , de telles fonctions prennent une liste de paramètres vide (dont le type n'est pas void , mais plutôt unit ).

Passage d'arguments

Le mécanisme exact d'attribution d'arguments aux paramètres, appelé passage d'arguments , dépend de la stratégie d'évaluation utilisée pour ce paramètre (généralement appel par valeur ), qui peut être spécifiée à l'aide de mots-clés.

Arguments par défaut

Certains langages de programmation tels que Ada , C++ , Clojure , Common Lisp , Fortran 90 , Python , Ruby , Tcl et Windows PowerShell permettent de donner explicitement ou implicitement un argument par défaut dans la déclaration d'un sous-programme. Cela permet à l'appelant d'omettre cet argument lors de l'appel du sous-programme. Si l'argument par défaut est explicitement donné, alors cette valeur est utilisée si elle n'est pas fournie par l'appelant. Si l'argument par défaut est implicite (parfois en utilisant un mot-clé tel que Optional ) alors le langage fournit une valeur connue (telle que null , Empty , zero, une chaîne vide, etc.) si une valeur n'est pas fournie par l'appelant .

Exemple PowerShell :

function doc($g = 1.21) {
    "$g gigawatts? $g gigawatts? Great Scott!"
}
PS  > doc
1.21 gigawatts? 1.21 gigawatts? Great Scott!

PS  > doc 88
88 gigawatts? 88 gigawatts? Great Scott!

Les arguments par défaut peuvent être considérés comme un cas particulier de la liste d'arguments de longueur variable.

Listes de paramètres de longueur variable

Certains langages permettent de définir des sous-programmes pour accepter un nombre variable d'arguments . Pour de tels langages, les sous-routines doivent parcourir la liste des arguments.

Exemple PowerShell :

function marty {
    $args | foreach { "back to the year $_" }
}
PS  > marty 1985
back to the year 1985

PS  > marty 2015 1985 1955
back to the year 2015
back to the year 1985
back to the year 1955

Paramètres nommés

Certains langages de programmation, tels que Ada et Windows PowerShell, permettent aux sous-routines d'avoir des paramètres nommés . Cela permet au code appelant d'être plus auto-documenté . Il offre également plus de flexibilité à l'appelant, permettant souvent de modifier l'ordre des arguments ou d'omettre des arguments selon les besoins.

Exemple PowerShell :

function jennifer($adjectiveYoung, $adjectiveOld) {
    "Young Jennifer: I'm $adjectiveYoung!"
    "Old Jennifer: I'm $adjectiveOld!"
}
PS  > jennifer 'fresh' 'experienced'
Young Jennifer: I'm fresh!
Old Jennifer: I'm experienced!

PS  > jennifer -adjectiveOld 'experienced' -adjectiveYoung 'fresh'
Young Jennifer: I'm fresh!
Old Jennifer: I'm experienced!

Paramètres multiples dans les langages fonctionnels

Dans le calcul lambda , chaque fonction a exactement un paramètre. Ce qui est considéré comme des fonctions avec plusieurs paramètres est généralement représenté dans le calcul lambda comme une fonction qui prend le premier argument et renvoie une fonction qui prend le reste des arguments ; c'est une transformation connue sous le nom de curry . Certains langages de programmation, comme ML et Haskell , suivent ce schéma. Dans ces langages, chaque fonction a exactement un paramètre, et ce qui peut ressembler à la définition d'une fonction de plusieurs paramètres, est en fait du sucre syntaxique pour la définition d'une fonction qui renvoie une fonction, etc. L'application de la fonction est associative à gauche dans ces langues ainsi que dans le calcul lambda, donc ce qui ressemble à une application d'une fonction à plusieurs arguments est correctement évalué comme la fonction appliquée au premier argument, puis la fonction résultante appliquée au deuxième argument, etc.

Paramètres de sortie

Un paramètre de sortie , également appelé paramètre de sortie ou paramètre de retour , est un paramètre utilisé pour la sortie, plutôt que l'utilisation plus habituelle pour l'entrée. Utiliser des paramètres d' appel par référence ou des paramètres d'appel par valeur où la valeur est une référence, car les paramètres de sortie sont un idiome dans certains langages, notamment C et C++, tandis que d'autres langages ont un support intégré pour les paramètres de sortie. Les langages avec prise en charge intégrée des paramètres de sortie incluent Ada (voir sous-programmes Ada ), Fortran (depuis Fortran 90 ; voir Fortran "intent" ), diverses extensions procédurales à SQL , telles que PL/SQL (voir fonctions PL/SQL ) et Transact -SQL , C# et le .NET Framework , Swift et le langage de script TScript (voir Déclarations de fonction TScript ).

Plus précisément, on peut distinguer trois types de paramètres ou modes de paramètres : paramètre d'entrée s,paramètres de sortieetparamètre d'entrée/sortie s ; ceux-ci sont souvent notésin,out, etin outouinout. Un argument d'entrée (l'argument d'un paramètre d'entrée) doit être une valeur, telle qu'une variable ou un littéral initialisé, et ne doit pas être redéfini ou affecté ; un argument de sortie doit être une variable assignable, mais il n'a pas besoin d'être initialisé, toute valeur existante n'est pas accessible et doit recevoir une valeur ; et un argument d'entrée/sortie doit être une variable initialisée et assignable, et peut éventuellement se voir assigner une valeur. Les exigences exactes et l'application varient selon les langues - par exemple, dansAda 83,les paramètres de sortie ne peuvent être affectés qu'à, pas lus, même après l'affectation (cela a été supprimé dansAda 95pour supprimer le besoin d'une variable d'accumulateur auxiliaire). Celles-ci sont analogues à la notion d'unevaleurdans une expression étant une valeur r (a une valeur), une valeur l (peut être attribuée) ou une valeur r/valeur l (a une valeur et peut être attribuée ), respectivement, bien que ces termes aient des significations spécialisées dans C.

Dans certains cas, seules l'entrée et l'entrée/sortie sont distinguées, la sortie étant considérée comme une utilisation spécifique de l'entrée/sortie, et dans d'autres cas, seules l'entrée et la sortie (mais pas l'entrée/sortie) sont prises en charge. Le mode par défaut varie selon les langues : dans Fortran 90, l'entrée/sortie est par défaut, tandis que dans les extensions C# et SQL, l'entrée est par défaut, et dans TScript, chaque paramètre est explicitement spécifié comme entrée ou sortie.

Syntaxiquement, le mode paramètre est généralement indiqué par un mot-clé dans la déclaration de fonction, comme void f(out int x)en C#. Classiquement, les paramètres de sortie sont souvent placés à la fin de la liste des paramètres pour les distinguer clairement, bien que cela ne soit pas toujours suivi. TScript utilise une approche différente, où dans la déclaration de fonction les paramètres d'entrée sont répertoriés, puis les paramètres de sortie, séparés par deux points (:) et il n'y a pas de type de retour à la fonction elle-même, comme dans cette fonction, qui calcule la taille d'un texte fragment:

TextExtent(WString text, Font font : Integer width, Integer height)

Les modes de paramètres sont une forme de sémantique dénotationnelle , indiquant l'intention du programmeur et permettant aux compilateurs de détecter les erreurs et d'appliquer des optimisations - ils n'impliquent pas nécessairement une sémantique opérationnelle (comment se produit réellement le passage des paramètres). Notamment, alors que les paramètres d'entrée peuvent être implémentés par appel par valeur, et les paramètres de sortie et d'entrée/sortie par appel par référence - et c'est un moyen simple d'implémenter ces modes dans des langages sans support intégré - ce n'est pas toujours ainsi qu'ils sont. mis en œuvre. Cette distinction est discutée en détail dans la justification Ada '83, qui souligne que le mode de paramètre est abstrait à partir duquel le mécanisme de transmission de paramètre (par référence ou par copie) est réellement mis en œuvre. Par exemple, alors qu'en C# les paramètres d'entrée (par défaut, pas de mot clé) sont passés par valeur et que les paramètres de sortie et d'entrée/sortie ( outet ref) sont passés par référence, en PL/SQL les paramètres d'entrée ( IN) sont passés par référence, et la sortie et les paramètres d'entrée/sortie ( OUTet IN OUT) sont par défaut passés par valeur et le résultat copié, mais peuvent être passés par référence en utilisant l' NOCOPYastuce du compilateur.

Une construction syntaxiquement similaire aux paramètres de sortie consiste à affecter la valeur de retour à une variable portant le même nom que la fonction. Cela se trouve dans Pascal et Fortran 66 et Fortran 77 , comme dans cet exemple Pascal :

function f(x, y: integer): integer;
begin
    f := x + y;
end;

C'est sémantiquement différent en ce que lorsqu'elle est appelée, la fonction est simplement évaluée - il ne lui est pas passé de variable de la portée d' appel pour stocker la sortie.

Utilisation

L'utilisation principale des paramètres de sortie consiste à renvoyer plusieurs valeurs à partir d'une fonction, tandis que l'utilisation des paramètres d'entrée/sortie consiste à modifier l'état à l'aide de la transmission de paramètres (plutôt que par un environnement partagé, comme dans les variables globales). Une utilisation importante du renvoi de valeurs multiples est de résoudre le problème de semi - prédicat consistant à renvoyer à la fois une valeur et un état d'erreur – voir Problème de semi - prédicat : retour multivalué .

Par exemple, pour retourner deux variables d'une fonction en C, on peut écrire :

int width
int height;

F(x, &width, &height);

xest un paramètre d'entrée et widthet heightsont des paramètres de sortie.

Un cas d'utilisation courant en C et dans les langages associés est la gestion des exceptions , où une fonction place la valeur de retour dans une variable de sortie et renvoie un booléen correspondant à la réussite ou à l'échec de la fonction. Un exemple archétypal est la TryParseméthode dans .NET, en particulier C#, qui analyse une chaîne en un entier, retournant trueen cas de succès et falsed'échec. Celui-ci porte la signature suivante :

public static bool TryParse(string s, out int result)

et peut être utilisé comme suit :

int result;
if (!Int32.TryParse(s, result)) {
    // exception handling
}

Des considérations similaires s'appliquent au retour d'une valeur de l'un des nombreux types possibles, où la valeur de retour peut spécifier le type, puis la valeur est stockée dans l'une des nombreuses variables de sortie.

Désavantages

Les paramètres de sortie sont souvent déconseillés dans la programmation moderne, essentiellement parce qu'ils sont maladroits, déroutants et de niveau trop bas – les valeurs de retour courantes sont considérablement plus faciles à comprendre et à utiliser. Notamment, les paramètres de sortie impliquent des fonctions avec des effets secondaires (modification du paramètre de sortie) et sont sémantiquement similaires aux références, qui sont plus déroutantes que les fonctions et valeurs pures, et la distinction entre paramètres de sortie et paramètres d'entrée/sortie peut être subtile. En outre, étant donné que dans les styles de programmation courants, la plupart des paramètres sont simplement des paramètres d'entrée, les paramètres de sortie et les paramètres d'entrée/sortie sont inhabituels et donc susceptibles d'être mal compris.

Les paramètres de sortie et d'entrée/sortie empêchent la composition de fonction , puisque la sortie est stockée dans des variables, plutôt que dans la valeur d'une expression. Ainsi, il faut d'abord déclarer une variable, puis chaque étape d'une chaîne de fonctions doit être une instruction distincte. Par exemple, en C++ la composition de fonction suivante :

Object obj = G(y, F(x));

lorsqu'il est écrit avec des paramètres de sortie et d'entrée/sortie devient (car Fc'est un paramètre de sortie, pour Gun paramètre d' entrée/sortie) :

Object obj;
F(x, &obj);
G(y, &obj);

Dans le cas particulier d'une fonction avec un seul paramètre de sortie ou d'entrée/sortie et sans valeur de retour, la composition de la fonction est possible si le paramètre de sortie ou d'entrée/sortie (ou en C/C++, son adresse) est également retourné par la fonction, auquel cas ce qui précède devient :

Object obj;
G(y, F(x, &obj));

Alternatives

Il existe différentes alternatives aux cas d'utilisation des paramètres de sortie.

Pour renvoyer plusieurs valeurs à partir d'une fonction, une alternative consiste à renvoyer un tuple . D'un point de vue syntaxique, cela est plus clair si le décompactage automatique de la séquence et l' affectation parallèle peuvent être utilisés, comme dans Go ou Python, par exemple :

def f():
    return 1, 2
a, b = f()

Pour renvoyer une valeur d'un type parmi plusieurs, une union étiquetée peut être utilisée à la place ; les cas les plus courants sont les types nullables ( types d' options ), où la valeur de retour peut être null pour indiquer un échec. Pour la gestion des exceptions, on peut retourner un type nullable ou lever une exception. Par exemple, en Python, on peut avoir soit :

result = parse(s)
if result is None:
    # exception handling

ou, plus idiomatiquement :

try:
    result = parse(s)
except ParseError:
    # exception handling

La micro-optimisation consistant à ne pas nécessiter de variable locale et à copier le retour lors de l'utilisation de variables de sortie peut également être appliquée aux fonctions conventionnelles et aux valeurs de retour par des compilateurs suffisamment sophistiqués.

L'alternative habituelle aux paramètres de sortie en C et dans les langages associés consiste à renvoyer une seule structure de données contenant toutes les valeurs de retour. Par exemple, étant donné une structure encapsulant largeur et hauteur, on peut écrire :

WidthHeight width_and_height = F(x);

Dans les langages orientés objet, au lieu d'utiliser des paramètres d'entrée/sortie, on peut souvent utiliser call by sharing , passer une référence à un objet puis muter l'objet, sans changer l'objet auquel la variable fait référence.

Voir également

Remarques

Les références