Codingly

Arguments nommés et arguments par défaut en C#4

Posted in Posts by Romain Verdier on avril 18, 2010

Guest post de Jb Evain.

J’ai un nouveau pet-peeve [1]. Mais comme pour beaucoup d’entre eux, c’est parce que je me suis longtemps fait avoir. Now that I saw the light, et que je ne me trompe guère plus, voir les autres se tromper m’est tout bonnement insupportable. D’ailleurs mon introduction est amusante, car beaucoup de français ont pour «pet-peeve» l’over utilisation des mots anglais dans une phrase française. Moi qui passe ma journée à lire et à écrire de l’anglais, ça ne me choque plus, vous savez.

Maintenant que vous, fidèle lectorat de Codingly, êtes tiraillé par le suspens, je me vois mal vous expliquer que c’est la mauvaise utilisation d’un mot qui cause toute cette ire. Et pourtant, ce matin encore, en lisant mon greader, j’ai failli en recracher mon thé équitable. Une personne de plus dans l’erreur, bordel ! J’en ai ouvert mon Word, et me voici deux paragraphes plus tard. Oui, j’en viens au cœur du problème. Problème que l’apparition de C#4 n’a pas manqué de raviver.

Prenons un exemple de code, compréhensible par tous de 7 à 77 ans. Exception faite de Patrick Smacchia qui dominait la scène démo bien avant cet âge.

public static void DoFoo ()
{
    string a = "b";
    string b = "b2";
    string c = "g";
    Foo (a, b, c);
}

public static string Foo (string bar, string baz, string gazonk)
{
    return bar + baz + gazonk;
}

Ce code n’a, je vous l’accorde, ni queue ni tête, et ne sert que le besoin de ma démonstration. Ne nommez pas vos variables ainsi (en plus vous devriez utiliser var, on voit bien que c’est un string). Ne refaites donc pas ça au travail. Chez vous, par contre, je dis pas, vous faites ce que vous voulez chez vous après tout.

Bref, détaillons rapidement ce petit bout de code. La méthode Foo a trois paramètres, bar, baz et gazonk. La méthode DoFoo déclare trois variables a, b et c, et appelle la méthode Foo en lui passant en argument le contenu de ses trois variables respectives.

Jusque ici, rien de bien terrible. Utilisons les nouveautés de C#4 maintenant.

public static void DoFoo ()
{
    string a = "foo";
    Foo (a);
    Foo (a, gazonk : "GazouGazou");
}

public static string Foo (string bar, string baz = "baz", string gazonk = "gaz")
{
    return bar + baz + gazonk;
}

C’est vrai que c’est amusant. Relisons encore ce que nous voyons. La méthode Foo a toujours trois paramètres, bar, baz et gazonk. Cependant, baz et gazonk ont maintenant une valeur d’argument par défaut. Pour le paramètre baz, la valeur "baz" sera passée comme argument par défaut si l’appelant n’en fournit pas, d’argument. Et de même pour le paramètre gazonk, qui aura comme argument par défaut la valeur "gaz".

La méthode DoFoo devient elle aussi plus intéressante. Elle appelle la méthode Foo deux fois. La première fois en passant un seul argument à Foo, le contenu de la variable a. Point besoin de passer d’autres arguments : le compilateur C# le fera à votre place. En examinant la signature de Foo, pour chaque paramètre définit par Foo, le compilateur va utiliser les valeurs nouvellement spécifiées comme valeurs d’arguments par défaut. Il n’y a donc pas besoin de passer d’argument pour les paramètres baz et gazonk. Après tout, c’est pour ça qu’on les appelle arguments par défaut.

Le deuxième appel à Foo est tout aussi intéressant. Non seulement on passe toujours comme argument le contenu d’une variable pour le paramètre a, mais en plus on spécifie clairement un argument, la valeur "GazouGazou" en le nommant, gazonk, d’après le paramètre définit dans la signature de la méthode Foo auquel on envie que le compilateur C# applique l’argument.

Oh je vous entends d’ici :

Tu nous saoules Jb, ça fait mille ans que c’est sorti C#4, et presque autant que je peux les utiliser avec Mono. En plus c’est super fastidieux ton explication, t’appuies sur tous les mots comme un gamin sur son jouet fisher price.

Et vous auriez raison. Mais les trucs fastidieux c’est un peu la raison d’être, comme disent les anglais, de Codingly. Donc mon article a tout à fait sa place.

De toute façon personne n’a rien compris, c’est pas un post sur comment ça marche les arguments nommés en C#4 et les arguments par défaut. C’est un post sur la bonne utilisation des mots « paramètre » et « argument » que tout le monde s’amuse à mélanger à loisir, et ce faisant, à ruiner mon bon moral dès le matin. Vous pourriez d’ailleurs aller lire Wikipedia ils expliquent mieux que moi.

Vous ne vous rendez pas compte, même les speakers aux TechDays se mélangent les pinceaux. Il y aurait eu des caténaires entre Lyon et Paris ce jour là, je me serais probablement évanoui dans la salle.

Récapitulons, donc :

  • Les paramètres nommés ne sont pas une nouveauté de C#4, depuis C#1 les paramètres ont des noms, enfin ! Un paramètre est un élément de la signature d’une méthode.
  • Un argument désigne la valeur passée à un paramètre. On peut maintenant nommer les arguments pour gagner en lisibilité. On peut aussi les omettre quand un paramètre définit une valeur d’argument par défaut.

C’est compris, OK ?

[1] Un «pet-peeve», comme vous ne manquez pas de le savoir, c’est quelque chose qui vous irrite sans que vous puissiez le contrôler de manière rationnelle.

Tagged with: , ,

27 Réponses

Subscribe to comments with RSS.

  1. Yann Schwartz said, on avril 18, 2010 at 10:22

    Un seul commentaire :

    http://moronail.net/img/2685_me_and_my_friend_are_real_glad_to_finally_meet_you

    Ah non, un deuxième :

    bien dit !

    Et bravo pour ce faisant.

  2. Julien said, on avril 19, 2010 at 7:43

    Je ferai attention maintenant, Merci de m’avoir montré la lumière :-)

  3. Laurent Le Brun said, on avril 19, 2010 at 10:22

    Moi, ce que je remarque, c’est que Wikipédia, que tu mentionnes pourtant, dit ça : http://en.wikipedia.org/wiki/Named_parameter

  4. Jb Evain said, on avril 19, 2010 at 10:34

    Et oui, la confusion est excessivement courante, et mine de rien, sujet à débat.

    Et puis ça se saurait si Wikipedia était tout le temps correcte. La MSDN elle, me semble exact pour C#4 : http://msdn.microsoft.com/en-us/library/dd264739.aspx et pourtant jette le doute une page plus loin: http://msdn.microsoft.com/en-us/library/f25e2b6b.aspx en même temps ça se saurait aussi la MSDN était tout le temps correcte.

    Qui croire ? Moi ? La MSDN ? Wikipédia ?

    • Emmanuel Deloget said, on juillet 31, 2012 at 2:27

      On dit « Le » MSDN. Parce qu’on parle du Microsoft Developper Network (MS est dérivé du nom de Microsoft avant qu’ils ne changent de nom, c’est à dire Micro Soft), ce qui est (rammené en Français), assez masculin.

      Ceci dit, bon article, qui a même réussi (grâce au ton utilisé) a provoquer chez moi un sourire, puis un rire (et c’est rare, lorsqu’on lit un blog technique). J’aime bien.

  5. Sebastien Benistant said, on avril 19, 2010 at 10:39

    C’est dingue, j’ai l’impression d’avoir compris ce que dit Romain cette fois ci.

    • Sebastien Benistant said, on avril 19, 2010 at 10:40

      Ah oui, c’est parce que c’est un guest post … je me disais aussi ;-)

  6. […] This post was mentioned on Twitter by Jb Evain, Jb Evain. Jb Evain said: J'ai écris pour le fantastique blog de @romainverdier sur les arguments optionnels et nommés: http://crum.pl/d5pu #Codingly #SaleProgrammeur […]

  7. Rubix said, on avril 19, 2010 at 9:27

    Eh bien non, je refuse ! Ce sont les paramètres qui sont nommés.
    Seulement, contrairement au C#1, 2 ou 3, ils sont nommés à l’appel en plus de l’être à la déclaration, tout simplement.

    Tu pars arbitrairement du principe que dans ‘Foo(a, gazonk : « GazouGazou »)’, c’est l’argument, la *valeur* « GazouGazou », auquel on donne un nom (gazonk). Nommer l’argument ? Mais pour quoi faire, grands dieux ?

    Il se sent morose, seul et impersonnel, l’argument, peut-être ? Il nous fait une crise d’identité, il veut marquer sa personnalité ? Il veut qu’on lui trouve un prénom ? « Bonjour, je m’appelle Charlotte, j’suis la petite string de la ligne 32, vous savez, celle avec l’arrobase sur l’oreille gauche… »

    Nommer l’argument ? Que nenni ! L’utilité, la raison d’être même du nommage, c’est de savoir résoudre en tant que quel *paramètre* sera passé l’argument à la fonction appelée.

    C’est donc dès le départ d’un nom de paramètre que l’on parle, et si ce n’en est pas un, le nom n’est pas valide (sans égards pour les sentiments de l’argument). C’est bien ce nom de paramètre qu’on associe via les deux-points à un argument, qui lui, reste dans l’anonymat ordinaire des expressions banales.

    • Jb Evain said, on avril 19, 2010 at 10:04

      Hiiii, j’adore.

      Mais je ne suis pas d’accord. Ça tombe bien, toi non plus.

      Les paramètres sont nommés, là dessus on est bien d’accord. Ils sont nommés depuis C#1, où tous les paramètres (ou presque, mais pour on va considérer que tous), ont un nom.

      Par contre, à l’appel, au «call site», la notion de paramètre n’existe pas vraiment. Un paramètre est une information qui appartient à la signature d’une méthode. Au call site, tout ce qu’on fait, c’est passer des arguments. Et on ne passe pas des argument en tant que paramètre, ça n’a pas de sens. On passe juste des arguments à une méthode.

      Et on est d’accord sur un point. On utilise le nom du paramètre pour nommer l’argument, sinon ça n’a pas de sens (dans un langage comme C# en tout cas). Et contrairement à ce que tu dis, le but est effectivement de simplifier l’appel de certaines méthodes qui possèdent dans leur signature une suite de paramètres qui rendent l’appel de cette méthode parfois difficile à lire.

      C’est typiquement le cas des méthodes avec des int index, int count, int truc. Et c’est encore plus typiquement le cas avec des bool. Combien de fois on voit des trucs genre:

      ReadFile (path, true);

      Et on a aucune idée de ce que true veut dire.

      ReadFile (path, readOnly : true)

      Apporte un confort de lecture, une facilité de compréhension immédiate. Parce que l’argument true, on l’a nommé. Et je ne parle pas de l’interop COM.

      La spec de C#4 est d’ailleurs claire, et définit la syntaxe pour les arguments nommés ainsi:

      argument:
      argument-nameopt argument-value
      argument-name:
      identifier :
      argument-value:
      expression
      ref variable-reference
      out variable-reference

      Et spécifie:

      «When determining the applicability of a function member the list of arguments are mapped to the formal parameters of the function member. The positional arguments are mapped to the parameters in the corresponding positions, and the named arguments are mapped to the parameters with the corresponding names.»

      Donc non, je suis bien d’accord avec moi même, en C#4, on nomme les arguments, et ils sont parfois optionnels.

      • Jb Evain said, on avril 19, 2010 at 10:11

        Cela dit, et pour le pur plaisir d’alimenter la polémique, le draft de la spec de C# se permet le luxe d’utiliser dans son introduction un titre «19.2 Named and optional parameters», où ils disent:

        «Parameters in C# can now be specified as optional by providing a default value for them in a member declaration. When the member is invoked, optional arguments can be omitted. Furthermore, any argument can be passed by parameter name instead of position.»

        Ce qui est consistent avec ce que je raconte, avec un titre horrible. Le reste de la spec est très clair et utilise de manière consistante arguments optionnels et arguments nommés.

      • Rubix said, on avril 19, 2010 at 11:14

        Haha, mais je re-proteste ! Faut dire, ce ne serait pas marrant si on était d’accord :)
        Il n’y a qu’un endroit où voir les arguments comme étant nommés peut avoir un avantage, et c’est l’implémentation du compilateur, pour des raisons purement techniques. En aucun cas ne laisserai-je ma vision haut-niveau du langage être influencée par de tels détails sous-jacents. Je m’explique.

        Il est clair, sans même devoir lire la spec, qu’un call site, avant de pouvoir être considéré par le compilateur comme une association entre des arguments et les paramètres d’une fonction, doit d’abord être résolu. En interne, le compilo part des résultats du parseur, qui sont, certes, des arguments et les noms qui leur sont associés. Au niveau du parsing, il est donc normal de parler de noms d’arguments, ce que fait la spec. C’est seulement dans une phase ultérieure que le bon overload a appeler est déterminé.

        Mais ! Cette compréhension, bien que nécessaire pour le compilateur, est purement, bassement, grossièrement voire vulgairement, im-plé-men-ta-toire.

        Dès lors que l’on ne s’intéresse plus au parsing, dès lors qu’on considère qu’on connait la fonction qui sera appelée (et ses paramètres, et l’association des arguments aux paramètres, que cette association ait été trouvée par position ou par nom), bref : quand on se place au point de vue du développeur… Alors la vision des arguments comme étant nommés n’a non seulement plus aucun intérêt pratique, mais elle aussi nuit à la compréhension (par exemple en suggérant que le nom puisse ne pas être un nom de paramètre). Les utilisateurs du langage se placent à un niveau d’abstraction plus élevé que le compilo.

        Sur ReadFile(path, readOnly : true), quand tu dis, « l’argument true, on l’a nommé », oui, tu as raison : on l’a nommé… d’un nom de paramètre existant. Sémantiquement, on ne l’a pas nommé dans le sens usuel « donner un nom », on l’a simplement rattaché à un nommé existant. Et c’est ce rattachement qui est important. Le « confort de lecture », la « facilité de compréhension immédiate », ils viennent du fait qu’on connait l’association de ce « true » au *paramètre*. L’argument est nommé… mais le nom est un nom de paramètre. Sans paramètre d’une fonction appelée, tout nommage de l’argument serait un non-sens (d’ailleurs je ne crois pas que ça compile gentiment).

        Voir les paramètres comme étant nommés au call site, tout en étant aussi exact, fait plus de sens (et moi je fais plus d’anglicismes), et c’est ce qui compte pour l’utilisation du langage (à contraster avec l’implémentation du langage, qui est quelque chose de nettement moins fréquent, sauf parmi ceux qui lisent la spec).

        Pour moi ça restera donc « paramètres nommés (et optionnels) à l’appel ».

  8. Jb Evain said, on avril 19, 2010 at 11:44

    Bizarrement je ne peux pas cliquer sur répondre. Alors je réponds comme je peux.

    Mon cher Rubix, quand tu dis «oui, tu as raison», je pense que tu as raison. En ce sens que j’ai raison.

    Je ne comprends pas pourquoi tu tiens à faire la distinction entre l’implémentation du langage et son implémentation. Si dans l’implémentation du compilateur C#, on parle de type valeur, c’est important qu’on parle de la même chose qu’un type valeur du point de vue de l’utilisateur du langage.

    Et bien pour les arguments et les paramètres c’est la même chose. On utilise le terme adéquat. Mais comme tu as l’air très convaincu, et que moi aussi, je vais devoir utiliser l’argument d’autorité, rubix sur l’ongle, avant d’en rester là. Anders Hejlsberg est d’accord avec moi. Ou l’inverse.

    Sinon on devrait poser ça comme question stackoverflow, assurément, ça ferait plein de brouzoufs, strike that, de rep’.

  9. smo said, on avril 20, 2010 at 1:25

    Argument nommés? Arguments optionnels? rhaaa… mais c’est le retour de Automation! (ou IDispatch pour les teigneux, ne pas confondre avec VB 3->6 bien que le premier a été crée pour le deuxième par ce monsieur http://www.microsoft.com/presspass/exec/techfellow/Lovering qui étrangement a travaillé ensuite sur VJ++ avec Hejlsberg avant d’être vraiment cool… comprenne qui peut). Pour les vieux comme moi, ça fait drôle de trouver dans C#4 ou DLR des idées (pas forcément des implémentations exactement identiques) qui existent depuis allez… 1992, dans des langages alors honnis par la communauté objet bien pensante :)

    Ok, ça fait vieux croulant, mais bah… j’ai aussi fait partie de la demo scene avec mon Atari 1040, moi (ah? ça s’appelait comme ça?)… mais encore avant. Roulez jeunesse!

    • Jb Evain said, on avril 20, 2010 at 8:53

      Oh c’était pas l’objet de ce post de les présenter comme une grande nouveauté. Et puis bon, 92, pas de quoi frimer, on les avait déjà en Smalltalk 80. (80 pour 1980, mais écrit dans les années 70). Et puis en 86 avec Objective-C, mais c’est pas étonnant, c’est très inspiré par Smalltalk.

      (Et puis placer `cool` c’était easy quand même, NGWS, ça aurait été plus balèze).

      • smo said, on avril 20, 2010 at 8:20

        arf c’est vrai, j’ai honte… Pas sûr que cool soit plus connu que NGWS… mais c’est vrai NGWS n’a pas duré bien longtemps, le temps d’une (fameuse) PDC, d’ailleurs je n’y pensais même plus!

  10. Rubix said, on avril 20, 2010 at 7:56

    Qu’ouï-je ? L’argument d’autorité ?.. Serait-ce que tu t’es déjà lassé du sujet[1] ? Si on en est là, je peux répondre google fight, même plus besoin de troller[2]… Déjà que tous les experts planétaires du C# mélangent allègrement les deux d’une phrase à l’autre, à l’instar de la spec…

    [1] : sujet qui traite pourtant d’une différence sémantique d’une ampleur tout à fait fondamentale à la bonne compréhension (donc utilisation) des appels de fonctions !
    [2] : alors que c’est manifestement le but initial…

    • Jb Evain said, on avril 20, 2010 at 8:38

      En fait, on pourrait continuer mille ans, et en être toujours au même point. Mais pour calmer les esprits échauffés dès le matin, on pourrait citer Jon Skeet 08.10.1/9.11:

      «Il n’y a qu’un Argument et qu’un Parameter, et ils sont interchangeables».

      http://stackoverflow.com/questions/156767/whats-the-difference-between-an-argument-and-a-parameter

      • Rubix said, on avril 20, 2010 at 7:57

        Ah, voilà un point de vue plus modéré que dans le post :)

      • Yann Schwartz said, on avril 28, 2010 at 11:01

        Cher jb, tu te vois décerner un point Skeet. Toute conversation sur C# qui dérive sur une mention de Jon Skeet (ou une photo de son peignoir) est considérée comme close.

        C’est malin.

  11. Cyril Martin said, on juin 3, 2010 at 7:57

    Merci Romain pour ce petit rappel sur la différence entre « paramètre » et « argument ». Mais j’ai à redire sur la conclusion… Je suis globalement d’accord avec Rubix: parler d’argument nommé me semble être une erreur.

    Je rejoins tout de même JB sur la mauvaise distinction langage / implémentation de la VM. Les mots ont un sens et doivent n’en avoir qu’un quelque soit la situation. On est des scientifiques non :-) ?

    Pour refuter l’expression « argument nommé », j’utiliserai donc un dictionnaire! En informatique comme ailleurs, donner un nom à une chose sert à la désigner. Quand on écris ReadFile(path, readOnly : true) est-ce que quelqu’un, quelque part va utiliser le nom « readOnly » pour retrouver la valeur true ?

    Jetons rapidement un coup d’oeuil sur le fonctionnement de la VM pour conclure que ce n’est pas important :)

    On pourrait imaginer qu’une méthode dite «avec des paramètres nommés» soit en réalité (en fouillant bien bas) une méthode qui prendrait un environnement (clefs/valeurs) en « argument » et qui en préambule chercherait les valeurs à affecter aux paramètres grâce à leur nom… Dans ce cas là il serait légitime de parler d’argument nommé…

    Ce qu’il se passe est exactement le contraire: lorsque l’on compile l’appel ReadFile(path, readOnly : true), on utilise le nom « readOnly » pour trouver qu’il s’agit du deuxième paramètre et ainsi empiler les arguments dans le bonne ordre…

    Tout cela est bien beau, mais cela n’a aucune importance finalement. Le bon programmeur lambda se fie à la spec du langage et ne veut pas imaginer comment c’est codé derrière (sauf peut-être par curiosité, le bon programmeur est curieux). Et on ne veut évidemment pas changer de vocable suivant l’implémentation de la VM. Donc il me semble impropre (no relevant pour Romain qui passe sa journée à lire de l’anglais) d’utiliser ces « arguments » là.

    La seule chose vraiment importante est l’intention du programmeur. Tout cela est en partie suggestif, mais c’est plus simple si l’on est d’accord sur les mots et les concepts.

    Reprennons l’exemple ReadFile(path, readOnly : true). Nous sommes d’accord pour dire que cette façon d’écrire facilite la lecture: humain et compilateur comprenons que cet argument « true » sera la valeur du paramètre « readOnly » durant l’interprétation de la méthode « ReadFile ».

    Malgré tous mes efforts, je n’arrive à me convaincre que mon intention de programmeur pourrait être de donner un nom à cette valeur « true » que je passe en argument. Et si c’était le cas, il me semblerait normal de pouvoir choisir n’importe quel nom.
    Personnellement il me semble plus correct de dire que l’on annote l’argument avec le nom d’un paramètre. Parler d’argument nommé est donc un raccourci malheureux qui introduit de la confusion.

    Cyril Martin.

    • Romain Verdier said, on juin 3, 2010 at 8:21

      (Juste une petite précision : cet article n’est pas de moi ; il a été rédigé par un invité — Jb en l’occurence.)

    • Jb Evain said, on juin 4, 2010 at 12:27

      Oh, de l’activité.

      Cyril, ça ne va pas être étonnant, mais je ne suis toujours pas d’accord. Tu axes ta démonstration sur trois points.

      1) le dictionnaire.

      Oui, le compilateur maintient un dictionnaire de clef valeur pour les appels avec arguments nommés. C’est nécessaire car ils peuvent être dans le désordre.

      2) Le fonctionnement de la VM.

      Les arguments nommés en C# ne sont que du sucre syntaxique. Et ce, pour la CLR, une VM très bas niveau. On peut imaginer C# tourner sur une autre machine, ou alors on peut prendre le point de vue d’autres langages plus dynamiques, où le concept de message passing est plus présent. Comme smalltalk. Allez, voir Objective-C. Et là, les arguments nommés prennent encore plus de sens car le nom de l’argument fait partie du «Message».

      3) La spec du langage.

      Comme je le montre, la spec du langage est claire, et parle d’arguments nommés.

      Là où je suis tout fait d’accord avec toi, c’est que l’utilisation du terme «annotation d’argument» est beaucoup plus proche de ce qui se passe réellement en C#.

      Mais il reste qu’en C#, on nomme quand même l’argument, du nom du paramètre dont l’argument sera la valeur.

      Et en conclusion, je dirais que je suis d’accord avec toi sur le fait que ça n’a pas grande importance, mais que comme tu le dis, il reste important d’utiliser les bons mots pour désigner les bonnes choses. Mais bon, la distinction est tellement mince qu’il est admit de pouvoir inter-changer les deux. L’important étant effectivement de pouvoir comprendre l’intention du code, de celui qui l’a écrit, et de pouvoir communiquer avec le même vocabulaire.

      • Cyril Martin said, on juin 5, 2010 at 2:05

        Mon commentaire n’était axé que sur un point et non trois: l’intention du programmeur. Pour répondre dans le désordre.

        1) Pour le dictionnaire, je parlais du petit Robert :-)

        3)
        > JB a dit
        > Mais il reste qu’en C#, on nomme quand même l’argument, du nom du paramètre dont l’argument sera la valeur.

        Voilà une phrase drôlement construite pour justifier le terme d’« argument nommé ». Moi qui est la souplesse d’esprit d’un cartésien maniaque, je crois que si l’on nomme un argument, c’est avec un nom d’argument. Et si c’est un nom d’argument alors ce nom réfère à (roulement de tambour) un argument. Or ce n’est pas le cas…

        2) Quant à SmallTalk… Oui le nom fait parti du message et pour les mêmes raisons qu’en (3) je réfute le terme de « nom d’argument ». Ce nom permet à l’objet qui reçoit le message de savoir à quel paramètre il doit affecter la valeur qui suit. Ce nom réfère donc à un paramètre, c’est un nom de paramètre.

        Cyril.

    • g2-b4172563295d990f03efc8d4cb6ee8fc said, on juillet 31, 2012 at 2:38

      > Merci Romain pour ce petit rappel sur la différence entre “paramètre” et “argument”.
      > Mais j’ai à redire sur la conclusion… Je suis globalement d’accord avec Rubix: parler
      > d’argument nommé me semble être une erreur.

      C’est bien de nuancer ton propos. Le fait qu’il te semble que ça soit une erreur devrait aider à te convaincre du contraire assez aisément.

      Le fait que, pour des raisons de sémantiques et de syntaxe, on soit obligé de donné à l’argument nommé le nom d’un paramètre n’est qu’une coïncidence liée d’une part à une volonté de simplifier la lecture du code (on sait en lisant le code de quel paramètre on parle) et d’autre part à simplifier grandement l’implémentation (qui n’a pas besoin de faire un travail considérable de recherche pour savoir à quelle place mettre l’argument). Ceci dit, je pourrais par exemple nommer l’argument en fonction de la position du paramètre ciblé ; dans le cas de l’exemple donné par JB, ça donnerais :

      Foo (a, 3 : « GazouGazou »);

      En supposant un index qui part de 1 (et non pas 0, ce qui rendrais le programme plus complexe). Au niveau de l’implémentation, ça permettrais de la simplifier encore davantage (accès direct dans un tableau au lieu d’une recherche dans la liste des paramètres) – mais celui qui lit le code aurait plus de problème. On reste donc sur la convention « on nomme l’argument avec le nom du paramètre », ce qui a beaucoup d’avantages et peu d’inconvénients.

      Le simple fait qu’on puisse utilisé un nommage alternatif (dans le cas cité, un ordre) démontre que ce n’est pas le paramètre qui est nommé (chose plus ou moins nécessaire), c’est l’argument qui est nommé selon le nom du paramètre.

  12. g2-b4172563295d990f03efc8d4cb6ee8fc said, on juillet 31, 2012 at 3:25

    >> JB a dit
    >> Mais il reste qu’en C#, on nomme quand même l’argument, du nom du paramètre
    >> dont l’argument sera la valeur.
    >
    > Voilà une phrase drôlement construite pour justifier le terme d’« argument nommé ».
    > Moi qui est la souplesse d’esprit d’un cartésien maniaque, je crois que si l’on nomme
    > un argument, c’est avec un nom d’argument. Et si c’est un nom d’argument alors ce
    > nom réfère à (roulement de tambour) un argument. Or ce n’est pas le cas…

    Il y a cartésianisme et cartésianisme. Plus exactement, il y a ceux qui pensent penser de manière cartésienne, et ceux qui, effectivement, pensent de manière cartésienne.

    Pour effectuer un raisonnement logique sur une phrase, il faut d’abord faire attention à sa grammaire. La grammaire fixe le type des mots utilisé, ce qui, en retour, et en fonction du fait que certains mots peuvent avoir plusieurs sens selon leur type, permet d’obtenir le sens des mots.

    A ce niveau, la phrase de JB est on ne peut plus claire et logique : on donne à l’argument un nom, et ce nom est celui du paramètre. De fait, le nom de l’argument est le même que celui du paramètre – ce qui ne signifie pas que ce n’est pas, pour autant, un nom d’argument.

    Le deuxième point dans une réflexion cartésienne consiste à faire très, très attention aux raisonnement induits. La phrase « Si A est vrai alors B est vrai » est, de manière trivialement compréhensible, illogique. Pourtant, c’est la structure de ton argument. Reprenons tes propositions :

    * Proposition 1 : si on nomme quelque chose, c’est avec le nom de cette chose
    * Proposition 2 : le nom d’une chose fait référence à cette chose.

    On remarque dans un premier temps qu’il n’y a pas de lien logique entre les deux proposition – il y a un lien sémantique, mais pas logique, dans le sens ou l’un ne découle pas de l’autre (ni dans un sens, ni dans l’autre). La première proposition peut être considérée comme vrai, encore qu’Eugène Ionesco a démontré que les mots utilisés pour décrire les choses étant arbitraires (conventionnels, plutôt), on peut les remplacer par d’autre et – en gardant un discours logique – garder le sens original de ce discours. Mais bon, globalement, et considérant que « nommer » signifie « donner un nom », on nomme quelque chose avec son nom – donc on nomme un argument avec son nom d’argument. Jusque là, difficile de dire le contraire.

    La seconde proposition pose plus de problème. Dans cette formulation, c’est une proposition illogique, car reposant sur un syllogisme consistant à penser qu’il n’existe qu’une seule chose portant un nom particulier. Ce n’est pas le cas, dans la vraie vie comme dans le domaine plus restreint de la programmation. Je peux avoir deux méthodes (donc deux choses différentes) portant le même nom ; en fait, le même token peut être utilisé autant de fois que souhaité dès lors que je respecte certaines règles. En fait, la seule manière (en rajoutant quelques mots) de rendre la proposition 2 logique, c’est de dire :

    Le nom d’une chose fait référence à au moins une chose portant ce nom.

    Pas génial.

    Concernant la structure du raisonnement, (ce que le décrit plus haut comme « Si A est vrai alors B est vrai »), il y a bien évidemment un problème. Tout simplement parce que donner un nom à quelque chose ne signifie pas que toute utilisation ultérieure de ce nom fasse référence à cette chose en particulier ; il n’y a aucune raison logique à ça. Tu t’appelles Cyril, et pourtant, je peut t’assurer que la plupart des Cyril que je rencontre ne sont pas toi. Là, on est dans la sémantique générale – le célèbre « la carte n’est pas le territoire ». On peut le reformuler en « le nom d’une chose ne fait pas nécessairement référence à une chose précise et particulière » (preuve par l’absurde, via une question à laquelle je vous laisse répondre : combien de pieds a une table ?)

    Du coup, il n’y a aucune raison pour que le nom d’un argument ne fasse référence qu’à un argument particulier. Il n’est pas absurde de penser qu’un nom d’argument puisse faire référence à autre chose, et en particulier à un paramètre identiquement nommé.

    Outre l’argument que j’ai précisé dans un autre commentaire (qui sera ou ne sera pas accepté (le commentaire ; l’argument, lui, devrait être compréhensible)), prenons le cas suivant.

    // déclaration de la méthode :
    int foo(int bar = 0, int baz = 1);
    // appel de la méthode :
    int k;
    k = foo(beer : 5);

    Evidemment, le compilateur va se plaindre, parce qu’il n’existe aucun paramètre nommé « beer ». Du coup, qu’est-ce que « beer », au niveau syntaxique, sinon un nom d’argument ? Le but du compilateur est donc de vérifier, dans ce cas précis, s’il y a corrélation entre le nom de l’argument et le nom du paramètre – dans le cas contraire, il signale une erreur. Cela n’empêche pas « beer » d’être un nom d’argument, puisqu’il n’est pas un nom de paramètre. Du coup, si je remplace « baz » dans la signature de la méthode par « beer », par quelle magie est-ce que mon premier « beer » (celui dont on vient de dire qu’il s’agissait d’un nom d’argument) deviendrait tout à coup un nom de paramètre ?

    J’espère que j’ai fait avancer la cause de JB :) (cause d’autant plus intéressante pour moi que je n’avais pas réfléchi à la question avant celà ; compréhensible, dans le sens ou ni le C, ni le C++ ne proposaient ce sucre syntaxique).

    • Rubix said, on juin 17, 2013 at 10:29

      Whoa ! Trois ans après, et complètement par hasard, je repasse sur les lieux du débat… De nouveaux arguments sont apparus, exprimés par de nouveaux intervenants (peut-on les appeler paramètres ?) de cette discussion, notamment de la part d’un certain « g2-b4172563295d990f03efc8d4cb6ee8fc », qui permettra je l’espère que je l’appelle g2.

      Résumons. A chaque callsite en C# 4, on peut choisir d’utiliser des ‘:’ afin de définir une association entre des noms et des expressions. Ces expressions sont appelées arguments, et les noms qui leurs sont associés serviront à être recoupés (de manière espérons-le valide) avec les noms des paramètres de la fonction que l’on souhaite appeler. Tout le monde est d’accord jusqu’ici, je pense.

      La divergence vient au moment d’interpréter cette association.

      Le camp des nommeurs d’arguments affirme que les noms associés aux arguments sont les noms des arguments, ce qui semble pertinent.
      La nouveauté du C# 4 serait donc bien la possibilité d’avoir des « arguments nommés ».

      Le camp des nommeurs de paramètres affirme que les noms associés aux arguments sont les noms des paramètres de la fonction appelée.
      La nouveauté du C# 4 serait donc plutôt la possibilité d’avoir des « paramètres nommés » *aux callsites* (je précise, puisque les paramètres étaient déjà nommés *à la déclaration*).

      Pour les uns, ce sont les noms que l’on affecte aux arguments. Pour les autres, ce sont les arguments que l’on affecte aux noms.

      L’exemple intéressant offert par « g2 », à mon sens, est celui-ci :

      int foo(int bar = 0, int baz = 1);
      k = foo(beer : 5); // un nom mais pas de paramètre, c’est donc un nom d’argument !

      Seulement, quitte à montrer du code qui ne compile pas, je peux aussi bien vous présenter cet exemple-ci :

      int foo(int bar = 0, int baz = 1);
      k = foo(bar: ); // un nom mais pas d’argument, c’est donc un nom de paramètre !

      En poussant plus loin, on peut invalider les deux points de vue :

      int foo(int bar = 0, int baz = 1);
      k = foo(beer: ); // un nom mais ni d’argument ni de paramètre, c’est donc… Un nom dans un appel de fonction ? Ou bien juste du texte sans aucun sens.

      On peut noter que le premier cas, à défaut de compiler, passait au moins le parsing. Cela m’amène à un intérêt que je vois à la compréhension « noms d’arguments » : c’est quand on est en train de suivre le comportement du compilateur. C’est utile de voir les choses ainsi puisque c’est dans cet ordre que la vérification est implémentée : on s’assure d’abord syntaxiquement de la présence du nom et de l’argument ; ensuite seulement on vérifiera le matching avec les paramètres. Donc dans l’interlude entre le parsing et le type-checking, oui, c’est utile de penser le nom comme un nom d’argument. C’est, je le soupçonne, la raison de l’adhésion de JB et g2 à cette compréhension.

      Mais je peux également trouver d’autres circonstances dans lesquelles c’est la compréhension alternative qui est la plus utile. Tiens : qui n’a jamais, dans Visual Studio, utilisé l’intellisense pour compléter le nom d’un paramètre nommé, avant d’écrire l’expression de l’argument lui correspondant ? Cette fois, dans l’interlude entre le choix du paramètre et le choix de l’expression, on connait déjà la fonction à appeler ainsi que ses paramètres, avant de décider de chaque expression à passer en argument. Dans cet exemple, c’est la vision « noms de paramètres » qui est utile.

      Bref, suivant la manière dont le code est invalide, les différentes interprétations du sens des noms ne se valent pas.
      Mais pour du code valide, les noms sont à la fois associés aux arguments et aux paramètres : je ne vois donc aucune raison objective d’affirmer qu’une des conceptions est meilleure que l’autre.

      Elles ont chacune leur intérêt dans des circonstances différentes. Il me semble donc malvenu, aujourd’hui tout autant qu’il y a trois ans, de vouloir imposer l’interprétation « arguments nommés » aux dépends de l’autre, tout aussi valide.

      Personnellement, mon pragmatisme me pousse à préférer l’intérpréatation « paramètres nommés », car je me pose plus souvent en tant qu’utilisateur du langage dans VS qu’en tant qu’implémenteur du compilateur.
      Même si je me doute bien que la majorité silencieuse continuera (et bien lui en prend) à préférer considérer que c’est une distinction sans intérêt à laisser aux pointilleux de la sémantique ayant trop de temps libre. :)

      Et je vous met au défi d’infirmer ce point de vue. Je vous laisse trois ans de plus pour trouver de nouveaux arguments :)


Répondre à Romain Verdier Annuler la réponse.