Désolé pour le titre maladroit - si je pouvais trouver un titre concis, je n'aurais pas à poser la question.
Supposons que j'ai un type de liste immuable. Il a une opération Foo(x)
qui retourne une nouvelle liste immuable avec l'argument spécifié comme élément supplémentaire à la fin. Donc, pour construire une liste de chaînes avec les valeurs "Bonjour", "immuable", "monde", vous pouvez écrire:
var empty = new ImmutableList<string>();
var list1 = empty.Foo("Hello");
var list2 = list1.Foo("immutable");
var list3 = list2.Foo("word");
(Il s'agit du code C #, et je suis plus intéressé par une suggestion C # si vous pensez que la langue est importante. Ce n'est pas fondamentalement une question de langue, mais les idiomes de la langue peuvent être importants.)
L'important est que les listes existantes ne soient pas modifiées par Foo
- donc empty.Count
retournerait toujours 0.
Une autre façon (plus idiomatique) d'arriver au résultat final serait:
var list = new ImmutableList<string>().Foo("Hello")
.Foo("immutable")
.Foo("word");
Ma question est: quel est le meilleur nom pour Foo?
EDIT 3 : Comme je le révèle plus tard, le nom du type pourrait ne pas être réellement ImmutableList<T>
, ce qui rend la position claire. Imaginez plutôt que c'est TestSuite
et qu'il est immuable car l'ensemble du cadre dont il fait partie est immuable ...
(Fin du montage 3)
Options que j'ai trouvées jusqu'à présent:
Add
: commun en .NET, mais implique une mutation de la liste d'origineCons
: Je crois que c'est le nom normal dans les langages fonctionnels, mais sans signification pour ceux qui n'ont pas d'expérience dans de tels langagesPlus
: mon préféré jusqu'à présent, cela n'implique pas de mutation pour moi . Apparemment, cela est également utilisé dans Haskell mais avec des attentes légèrement différentes (un programmeur Haskell pourrait s'attendre à ce qu'il ajoute deux listes ensemble plutôt que d'ajouter une seule valeur à l'autre liste).With
: cohérent avec d'autres conventions immuables, mais n'a pas tout à fait la même "addition" à l'OMI.And
: peu descriptif.- Surcharge de l'opérateur pour +: je n'aime vraiment pas beaucoup ça; Je pense généralement que les opérateurs ne devraient être appliqués qu'aux types de niveau inférieur. Mais je suis persuadé!
Les critères que j'utilise pour choisir sont:
- Donne l'impression correcte du résultat de l'appel de méthode (c'est-à-dire qu'il s'agit de la liste d'origine avec un élément supplémentaire)
- Indique aussi clairement que possible qu'il ne mute pas la liste existante
- Cela semble raisonnable lorsqu'il est enchaîné comme dans le deuxième exemple ci-dessus
Veuillez demander plus de détails si je ne me fais pas assez clair ...
EDIT 1: Voici mon raisonnement pour préférer Plus
à Add
. Considérez ces deux lignes de code:
list.Add(foo);
list.Plus(foo);
À mon avis (et c'est une chose personnelle), ce dernier est clairement buggé - c'est comme écrire "x + 5;" comme une déclaration à part entière. La première ligne semble correcte, jusqu'à ce que vous vous souveniez qu'elle est immuable. En fait, la façon dont l'opérateur plus seul ne mute pas ses opérandes est une autre raison pour laquelle Plus
je préfère. Sans la légère lourdeur de la surcharge des opérateurs, cela donne toujours les mêmes connotations, qui incluent (pour moi) de ne pas muter les opérandes (ou la méthode cible dans ce cas).
EDIT 2: Raisons de ne pas aimer Add.
Diverses réponses sont effectivement: "Allez avec Add. C'est ce qui DateTime
fait, et String
a des Replace
méthodes, etc. qui ne rendent pas l'immuabilité évidente." Je suis d'accord - il y a priorité ici. Cependant, j'ai vu beaucoup de gens appellent DateTime.Add
ou String.Replace
et attendent une mutation . Il y a des tas de questions de newsgroup (et probablement SO si je creuse) auxquelles répond "Vous ignorez la valeur de retour de String.Replace
; les chaînes sont immuables, une nouvelle chaîne est retournée."
Maintenant, je devrais révéler une subtilité à la question - le type peut ne pas être en fait une liste immuable, mais un type immuable différent. En particulier, je travaille sur un cadre d'analyse comparative où vous ajoutez des tests à une suite, et qui crée une nouvelle suite. Il pourrait être évident que:
var list = new ImmutableList<string>();
list.Add("foo");
ne va rien accomplir, mais cela devient beaucoup plus trouble lorsque vous le changez en:
var suite = new TestSuite<string, int>();
suite.Add(x => x.Length);
On dirait que ça devrait aller. Alors que cela, pour moi, rend l'erreur plus claire:
var suite = new TestSuite<string, int>();
suite.Plus(x => x.Length);
Cela ne demande qu'à être:
var suite = new TestSuite<string, int>().Plus(x => x.Length);
Idéalement, j'aimerais que mes utilisateurs n'aient pas à être informés que la suite de tests est immuable. Je veux qu'ils tombent dans le gouffre du succès. Ce n'est peut-être pas possible, mais j'aimerais essayer.
Je m'excuse d'avoir trop simplifié la question d'origine en ne parlant que d'un type de liste immuable. Toutes les collections ne sont pas aussi auto-descriptives que ImmutableList<T>
:)
Réponses:
Dans des situations comme ça, j'y vais habituellement
Concat
. Cela m'implique généralement qu'un nouvel objet est en cours de création.la source
J'irais avec les inconvénients, pour une raison simple: cela signifie exactement ce que vous voulez.
Je suis un grand fan de dire exactement ce que je veux dire, en particulier dans le code source. Un débutant devra rechercher la définition des inconvénients une seule fois, puis la lire et l'utiliser mille fois. Je trouve que, à long terme, il est plus agréable de travailler avec des systèmes qui facilitent le cas commun, même si le coût initial est un peu plus élevé.
Le fait que ce serait «insignifiant» pour les personnes sans expérience en PF est en fait un gros avantage. Comme vous l'avez souligné, tous les autres mots que vous avez trouvés ont déjà une signification, et cette signification est soit légèrement différente, soit ambiguë. Un nouveau concept doit avoir un nouveau mot (ou dans ce cas, un ancien). Je préfère que quelqu'un regarde la définition de Contre, plutôt que de supposer à tort qu'il sait ce que fait Add.
D'autres opérations empruntées aux langages fonctionnels gardent souvent leurs noms d'origine, sans catastrophe apparente. Je n'ai vu aucun effort pour trouver des synonymes de «carte» et de «réduction» qui semblent plus familiers aux non-FPers, et je ne vois aucun avantage à le faire.
(Divulgation complète: je suis un programmeur Lisp, donc je sais déjà ce que signifie Cons.)
la source
En fait j'aime bien
And
, surtout de façon idiomatique. J'aimerais particulièrement que vous ayez une propriété statique en lecture seule pour la liste vide, et peut-être rendre le constructeur privé afin que vous deviez toujours construire à partir de la liste vide.la source
Chaque fois que je suis dans un jam avec la nomenclature, je frappe les interwebs.
thesaurus.com renvoie ceci pour "ajouter":
J'aime le son de
Adjoin
, ou plus simplementJoin
. C'est ce que tu fais, non? La méthode pourrait également s'appliquer pour rejoindre les autresImmutableList<>
.la source
Personnellement, j'aime .With (). Si j'utilisais l'objet, après avoir lu la documentation ou les commentaires du code, il serait clair ce qu'il fait, et il se lit bien dans le code source.
Ou, vous ajoutez "Parallèlement" à cela .. :)
la source
J'ai fini par utiliser Add pour toutes mes collections immuables dans BclExtras . La raison en est que c'est un nom facile à prévoir. Je ne m'inquiète pas tant que les gens confondent Add avec un add mutant puisque le nom du type est préfixé par Immutable.
Pendant un certain temps, j'ai considéré les inconvénients et d'autres noms de style fonctionnel. Finalement, je les ai réduits parce qu'ils ne sont pas aussi bien connus. Bien sûr, les programmeurs fonctionnels comprendront, mais ils ne sont pas la majorité des utilisateurs.
Autres noms: vous avez mentionné:
Options que j'ai envisagées:
Malheureusement, il ne semble pas vraiment y avoir un mot qui soit
Cela devient encore plus étrange lorsque vous envisagez des collections autres que List. Prenez par exemple Stack. Même les programmeurs de première année peuvent vous dire que les piles ont une paire de méthodes Push / Pop. Si vous créez un ImmutableStack et lui donnez un nom complètement différent, appelons-le Foo / Fop, vous venez d'ajouter plus de travail pour qu'ils utilisent votre collection.
Edit: Réponse à Plus Edit
Je vois où tu vas avec Plus. Je pense qu'un cas plus solide serait en fait Minus à supprimer. Si je voyais ce qui suit, je me demanderais certainement à quoi pensait le programmeur
Le plus gros problème que j'ai avec Plus / Minus ou un nouvel appairage, c'est qu'il semble exagéré. La collection elle-même a déjà un nom distinctif, le préfixe immuable. Pourquoi aller plus loin en ajoutant du vocabulaire dont l'intention est d'ajouter la même distinction que le préfixe immuable l'a déjà fait.
Je peux voir l'argument du site d'appel. Cela le rend plus clair du point de vue d'une seule expression. Mais dans le contexte de l'ensemble de la fonction, cela semble inutile.
Modifier 2
Convenez que les gens ont définitivement été confondus par String.Concat et DateTime.Add. J'ai vu plusieurs programmeurs très brillants rencontrer ce problème.
Cependant, je pense que ImmutableList est un argument différent. Il n'y a rien sur String ou DateTime qui l'établit comme Immuable pour un programmeur. Vous devez simplement savoir qu'il est immuable via une autre source. La confusion n'est donc pas inattendue.
ImmutableList n'a pas ce problème car le nom définit son comportement. On pourrait dire que les gens ne savent pas ce qu'est Immutable et je pense que c'est également valable. Je ne le savais certainement pas avant la deuxième année au collège. Mais vous avez le même problème avec le nom que vous choisissez au lieu de Ajouter.
Edit 3: Qu'en est-il des types comme TestSuite qui sont immuables mais ne contiennent pas le mot?
Je pense que cela renvoie à l'idée que vous ne devriez pas inventer de nouveaux noms de méthode. À savoir parce qu'il y a clairement une volonté de rendre les types immuables afin de faciliter les opérations parallèles. Si vous vous concentrez sur la modification du nom des méthodes pour les collections, l'étape suivante sera le nom des méthodes de mutation sur chaque type que vous utilisez qui est immuable.
Je pense que ce serait un effort plus précieux de se concentrer plutôt sur la création de types identifiables comme immuables. De cette façon, vous pouvez résoudre le problème sans repenser chaque modèle de méthode de mutation.
Maintenant, comment pouvez-vous identifier TestSuite comme immuable? Dans l'environnement actuel, je pense qu'il y a plusieurs façons
Je suppose / espère que les outils de développement commenceront à résoudre ce problème en facilitant l'identification des types immuables simplement par la vue (couleur différente, police plus forte, etc.). Mais je pense que c'est la réponse cependant en changeant tous les noms de méthode.
la source
Je pense que cela peut être l'une de ces rares situations où il est acceptable de surcharger l'
+
opérateur. En terminologie mathématique, nous savons que cela+
n'ajoute pas quelque chose à la fin de quelque chose d'autre. Il combine toujours deux valeurs ensemble et renvoie une nouvelle valeur résultante.Par exemple, il est intuitivement évident que lorsque vous dites
la valeur résultante de x est 4, pas 22.
De même,
devrait indiquer clairement ce que chaque variable va contenir. Il doit être clair que cela
list2
n'est pas modifié dans la dernière ligne, mais à la place,list3
le résultat de l'ajout de "mot" àlist2
.Sinon, je nommerais simplement la fonction Plus ().
la source
[1] + 2 = [1,2]
mais[1] + [2] = [1,[2]]
. Ce que vous proposez, c'est un comportement incohérent. C'est probablement pourquoi Python ne vous permet pas d'ajouter un élément de cette façon.Pour être aussi clair que possible, vous voudrez peut-être aller avec le plus verbeux
CopyAndAdd
ou quelque chose de similaire.la source
Je l'appellerais Extend () ou peut-être ExtendWith () si vous vous sentez vraiment bavard.
Étendre signifie ajouter quelque chose à quelque chose d'autre sans le changer. Je pense que c'est une terminologie très pertinente en C # car elle est similaire au concept des méthodes d'extension - elles "ajoutent" une nouvelle méthode à une classe sans "toucher" la classe elle-même.
Sinon, si vous voulez vraiment souligner que vous ne modifiez pas du tout l'objet d'origine, utiliser un préfixe comme Get- me semble inévitable.
la source
Ajouté (), ajouté ()
J'aime utiliser le passé pour des opérations sur des objets immuables. Il transmet l'idée que vous ne changez pas l'objet d'origine, et il est facile à reconnaître lorsque vous le voyez.
De plus, comme les noms de méthode de mutation sont souvent des verbes au présent, cela s'applique à la plupart des cas de nom de méthode immuable que vous rencontrez. Par exemple, une pile immuable a les méthodes "push" et "popped".
la source
J'aime la suggestion de mmyers de CopyAndAdd . Conformément à un thème de «mutation», vous pourriez peut-être opter pour Bud (reproduction asexuée), Grow , Replicate ou Evolve ? =)
EDIT: Pour continuer avec mon thème génétique, que diriez-vous de Procréer , impliquant qu'un nouvel objet est créé qui est basé sur le précédent, mais avec quelque chose de nouveau ajouté.
la source
C'est probablement un tronçon, mais dans Ruby il y a une notation couramment utilisée pour la distinction:
add
ne mute pas;add!
mute. Si c'est un problème omniprésent dans votre projet, vous pouvez le faire aussi (pas nécessairement avec des caractères non alphabétiques, mais en utilisant systématiquement une notation pour indiquer les méthodes de mutation / non-mutation).la source
Join
semble approprié.la source
La confusion vient peut-être du fait que vous voulez deux opérations en une. Pourquoi ne pas les séparer? Style DSL:
Copy
renverrait un objet intermédiaire, c'est une copie modifiable de la liste d'origine.With
retournerait une nouvelle liste immuable.Mettre à jour:
Mais, avoir une collection intermédiaire et mutable n'est pas une bonne approche. L'objet intermédiaire doit être contenu dans l'
Copy
opération:Maintenant, l'
Copy
opération prend un délégué, qui reçoit une liste modifiable, afin qu'il puisse contrôler le résultat de la copie. Cela peut faire bien plus que l'ajout d'un élément, comme la suppression d'éléments ou le tri de la liste. Il peut également être utilisé dans leImmutableList
constructeur pour assembler la liste initiale sans listes immuables intermédiaires.Maintenant, il n'y a aucune possibilité de mauvaise interprétation par les utilisateurs, ils tomberont naturellement dans le gouffre du succès .
Encore une autre mise à jour:
Si vous n'aimez toujours pas la mention de liste modifiable, même maintenant qu'elle est contenue, vous pouvez concevoir un objet de spécification, qui spécifiera , ou un script , comment l'opération de copie transformera sa liste. L'utilisation sera la même:
Vous pouvez maintenant être créatif avec les noms de règles et vous ne pouvez exposer que les fonctionnalités que vous souhaitez
Copy
prendre en charge, et non toutes les capacités d'unIList
.Pour l'utilisation du chaînage, vous pouvez créer un constructeur raisonnable (qui n'utilisera pas le chaînage, bien sûr):
Ou utilisez le même délégué dans un autre constructeur:
Cela suppose que la
rules.Append
méthode retournethis
.Voici à quoi cela ressemblerait avec votre dernier exemple:
la source
Quelques réflexions aléatoires:
la source
DateTime en C # utilise Add. Alors pourquoi ne pas utiliser le même nom? Tant que les utilisateurs de votre classe comprennent que la classe est immuable.
la source
Je pense que l'élément clé que vous essayez d'obtenir, qui est difficile à exprimer, est la non-permutation, donc peut-être quelque chose avec un mot génératif, quelque chose comme CopyWith () ou InstancePlus ().
la source
Je ne pense pas que la langue anglaise vous laissera impliquer l'immuabilité d'une manière indubitable tout en utilisant un verbe qui signifie la même chose que "Ajouter". "Plus" le fait presque, mais les gens peuvent toujours faire l'erreur.
La seule façon d'empêcher vos utilisateurs de confondre l'objet avec quelque chose de mutable est de le rendre explicite, soit par le nom de l'objet lui-même, soit par le nom de la méthode (comme avec les options détaillées comme "GetCopyWith" ou "CopyAndAdd").
Alors, allez-y avec votre favori, "Plus".
la source
Tout d'abord, un point de départ intéressant: http://en.wikipedia.org/wiki/Naming_conventions_(programming) ... En particulier, consultez les liens "Voir aussi" en bas.
Je suis en faveur de Plus ou Et, de manière égale.
Plus et And sont tous deux basés sur les mathématiques en étymologie. En tant que tels, tous deux évoquent une opération mathématique; les deux produisent une expression qui se lit naturellement comme des expressions qui peuvent se résoudre en une valeur, ce qui correspond à la méthode ayant une valeur de retour.
And
porte une connotation logique supplémentaire, mais les deux mots s'appliquent intuitivement aux listes.Add
connote une action effectuée sur un objet, qui entre en conflit avec la sémantique immuable de la méthode.Les deux sont courts, ce qui est particulièrement important étant donné la primitivité de l'opération. Les opérations simples et fréquemment exécutées méritent des noms plus courts.
Exprimer une sémantique immuable est quelque chose que je préfère faire via le contexte. Autrement dit, j'impliquerais simplement que tout ce bloc de code a une sensation fonctionnelle; supposons que tout est immuable. Mais c'est peut-être juste moi. Je préfère l'immuabilité à la règle; si c'est fait, c'est beaucoup fait au même endroit; la mutabilité est l'exception.
la source
Que diriez-vous de Chain () ou Attach ()?
la source
visualthesaurus.com
(sans affiliation) lorsque j'ai cherchéconcatenate
.Je préfère Plus (et Moins). Ils sont facilement compréhensibles et correspondent directement aux opérations impliquant des types immuables bien connus (les nombres). 2 + 2 ne change pas la valeur de 2, il renvoie une nouvelle valeur, également immuable.
Quelques autres possibilités:
Épissure()
Greffer()
Accrete ()
la source
Que diriez-vous de mate , mateWith ou coït , pour ceux qui demeurent. En termes de reproduction, les mammifères sont généralement considérés comme immuables.
Va jeter Union là-bas aussi. Emprunté à SQL.
la source
Apparemment, je suis le premier Obj-C / Cocoa à répondre à cette question.
Je ne gagnerai aucun jeu de golf avec ce code.
la source
[object]By[Verb]ing[Object]:
préfixe de la méthode implique qu'une nouvelle chaîne sera retournée par opposition à simplement[verb][Object]:
, ce qui muterait l'objet en place.Je pense que "Ajouter" ou "Plus" sonne bien. Le nom de la liste elle-même devrait être suffisant pour exprimer l'immuabilité de la liste.
la source
Peut-être qu'il y a des mots qui me rappellent plus de faire une copie et d'ajouter des choses à cela au lieu de muter l'instance (comme "Concaténer"). Mais je pense que d'avoir une certaine symétrie pour ces mots pour d'autres actions serait bien d'avoir aussi. Je ne connais pas de mot similaire pour "Supprimer" auquel je pense du même genre que "Concaténer". "Plus" me semble peu étrange. Je ne m'attendrais pas à ce qu'il soit utilisé dans un contexte non numérique. Mais cela pourrait aussi provenir de mes antécédents non anglais.
Peut-être que j'utiliserais ce schéma
Cependant, ceux-ci ont leurs propres problèmes, quand j'y pense. On pourrait penser qu'ils retirent quelque chose ou ajoutent quelque chose à un argument donné. Pas sûr du tout. Je pense que ces mots ne jouent pas bien dans l'enchaînement. Trop verbeux pour taper.
Peut-être que j'utiliserais simplement "Ajouter" et mes amis aussi. J'aime la façon dont il est utilisé en mathématiques
Eh bien, certainement, un 2 reste un 2 et vous obtenez un nouveau numéro. Il s'agit de deux nombres et non d'une liste et d'un élément, mais je pense qu'il a une certaine analogie. À mon avis,
add
cela ne signifie pas nécessairement que vous mutez quelque chose. Je vois certainement votre point que le fait d'avoir une déclaration solitaire contenant juste unadd
et de ne pas utiliser le nouvel objet renvoyé ne semble pas bogué. Mais j'ai maintenant réfléchi à l'idée d'utiliser un autre nom que "ajouter" mais je ne peux pas trouver un autre nom sans me faire penser "hmm, il faudrait que je regarde la documentation pour savoir quoi il s'agit de "parce que son nom diffère de ce que j'attendrais d'être appelé" ajouter ". Juste une réflexion bizarre de la part de litb, pas sûr que cela ait du sens :)la source
En consultant http://thesaurus.reference.com/browse/add et http://thesaurus.reference.com/browse/plus, j'ai trouvé un gain et un affixe, mais je ne sais pas dans quelle mesure ils impliquent une non-mutation.
la source
Je pense que
Plus()
etMinus()
ou, alternativementIncluding()
,Excluding()
sont raisonnables pour impliquer un comportement immuable.Cependant, aucun choix de nom ne le rendra parfaitement clair pour tout le monde, donc je pense personnellement qu'un bon commentaire de doc xml irait très loin ici. VS les jette directement dans votre visage lorsque vous écrivez du code dans l'EDI - ils sont difficiles à ignorer.
la source
Append
- car, notez que les noms desSystem.String
méthodes suggèrent qu'ils mutent l'instance, mais ils ne le font pas.Ou j'aime bien
AfterAppending
:la source
list.CopyWith(element)
Tout comme Smalltalk :)
Et
list.copyWithout(element)
cela supprime également toutes les occurrences d'un élément, ce qui est très utile lorsqu'il est utilisélist.copyWithout(null)
pour supprimer des éléments non définis.la source
Je choisirais Add, car je peux voir l'avantage d'un meilleur nom, mais le problème serait de trouver des noms différents pour chaque autre opération immuable qui pourrait rendre la classe assez peu familière si cela a du sens.
la source