Perdón por el título waffly: si pudiera encontrar un título conciso, no tendría que hacer la pregunta.
Supongamos que tengo un tipo de lista inmutable. Tiene una operación Foo(x)
que devuelve una nueva lista inmutable con el argumento especificado como un elemento adicional al final. Entonces, para crear una lista de cadenas con los valores "Hola", "inmutable", "mundo", podría escribir:
var empty = new ImmutableList<string>();
var list1 = empty.Foo("Hello");
var list2 = list1.Foo("immutable");
var list3 = list2.Foo("word");
(Este es el código C #, y estoy más interesado en una sugerencia C # si considera que el idioma es importante. No es fundamentalmente una pregunta de idioma, pero los modismos del idioma pueden ser importantes).
Lo importante es que las listas existentes no se alteran, por Foo
lo empty.Count
que aún devolvería 0.
Otra forma (más idiomática) de llegar al resultado final sería:
var list = new ImmutableList<string>().Foo("Hello")
.Foo("immutable")
.Foo("word");
Mi pregunta es: ¿cuál es el mejor nombre para Foo?
EDITAR 3 : Como revelaré más adelante, el nombre del tipo podría no serlo ImmutableList<T>
, lo que aclara la posición. Imagine en cambio que es TestSuite
y que es inmutable porque todo el marco del que forma parte es inmutable ...
(Fin de la edición 3)
Opciones que se me han ocurrido hasta ahora:
Add
: común en .NET, pero implica la mutación de la lista originalCons
: Creo que este es el nombre normal en lenguajes funcionales, pero no tiene sentido para aquellos sin experiencia en dichos lenguajesPlus
: mi favorito hasta ahora, no implica mutación para mí . Aparentemente, esto también se usa en Haskell, pero con expectativas ligeramente diferentes (un programador de Haskell podría esperar que agregue dos listas juntas en lugar de agregar un solo valor a la otra lista).With
: consistente con algunas otras convenciones inmutables, pero no tiene la misma "incorporación" a la OMI.And
: no muy descriptivo.- Sobrecarga del operador para +: Realmente no me gusta tanto; En general, creo que los operadores solo deberían aplicarse a los tipos de nivel inferior. ¡Aunque estoy dispuesto a ser persuadido!
Los criterios que estoy usando para elegir son:
- Da la impresión correcta del resultado de la llamada al método (es decir, que es la lista original con un elemento adicional)
- Deja lo más claro posible que no muta la lista existente
- Suena razonable cuando se encadenan juntos como en el segundo ejemplo anterior
Solicite más detalles si no me estoy aclarando lo suficiente ...
EDIT 1: Aquí está mi razonamiento para preferir Plus
a Add
. Considere estas dos líneas de código:
list.Add(foo);
list.Plus(foo);
Desde mi punto de vista (y esto es algo personal), este último tiene errores, es como escribir "x + 5"; como una declaración por sí sola. Parece que la primera línea está bien, hasta que recuerdes que es inmutable. De hecho, la forma en que el operador plus por sí solo no muta sus operandos es otra razón por la cual Plus
es mi favorito. Sin la ligera aspereza de la sobrecarga del operador, todavía da las mismas connotaciones, que incluyen (para mí) no mutar los operandos (o el objetivo del método en este caso).
EDIT 2: Razones para no gustar Agregar.
Varias respuestas son efectivas: "Vaya con Agregar. Eso es lo que DateTime
hace, y String
tiene Replace
métodos, etc. que no hacen obvia la inmutabilidad". Estoy de acuerdo, hay prioridad aquí. Sin embargo, he visto un montón de personas que llaman DateTime.Add
o String.Replace
y esperan que la mutación . Hay un montón de preguntas de grupos de noticias (y probablemente SO si cavo) que son respondidas por "Estás ignorando el valor de retorno de String.Replace
; las cadenas son inmutables, se devuelve una nueva cadena".
Ahora, debo revelar una sutileza a la pregunta: el tipo podría no ser realmente una lista inmutable, sino un tipo inmutable diferente. En particular, estoy trabajando en un marco de evaluación comparativa en el que agrega pruebas a una suite, y eso crea una nueva suite. Puede ser obvio que:
var list = new ImmutableList<string>();
list.Add("foo");
no va a lograr nada, pero se vuelve mucho más oscuro cuando lo cambia a:
var suite = new TestSuite<string, int>();
suite.Add(x => x.Length);
Parece que debería estar bien. Mientras que esto, para mí, aclara el error:
var suite = new TestSuite<string, int>();
suite.Plus(x => x.Length);
Eso es solo rogar ser:
var suite = new TestSuite<string, int>().Plus(x => x.Length);
Idealmente, me gustaría que mis usuarios no tengan que decirles que el conjunto de pruebas es inmutable. Quiero que caigan en el pozo del éxito. Puede que esto no sea posible, pero me gustaría intentarlo.
Pido disculpas por simplificar demasiado la pregunta original al hablar solo de un tipo de lista inmutable. No todas las colecciones son tan autodescriptivas como ImmutableList<T>
:)
Respuestas:
En situaciones como esa, suelo ir con ellos
Concat
. Eso generalmente me implica que se está creando un nuevo objeto.fuente
Yo iría con Contras, por una simple razón: significa exactamente lo que quieres.
Soy un gran fanático de decir exactamente lo que quiero decir, especialmente en el código fuente. Un novato tendrá que buscar la definición de Contras solo una vez, pero luego leerla y usarla miles de veces. Creo que, a largo plazo, es mejor trabajar con sistemas que facilitan el caso común, incluso si el costo inicial es un poco más alto.
El hecho de que sería "sin sentido" para las personas sin experiencia en FP es en realidad una gran ventaja. Como señaló, todas las otras palabras que encontró ya tienen algún significado, y ese significado es ligeramente diferente o ambiguo. Un nuevo concepto debe tener una nueva palabra (o en este caso, una antigua). Prefiero que alguien tenga que buscar la definición de Contras, que suponer incorrectamente que sabe lo que hace Add.
Otras operaciones prestadas de lenguajes funcionales a menudo mantienen sus nombres originales, sin catástrofes aparentes. No he visto ningún impulso para encontrar sinónimos de "mapa" y "reducir" que suenen más familiares para los que no son FPers, ni veo ningún beneficio al hacerlo.
(Divulgación completa: soy un programador Lisp, así que ya sé lo que significa Contras).
fuente
En realidad me gusta
And
, especialmente en la forma idiomática. Me gustaría especialmente si tuviera una propiedad de solo lectura estática para la lista vacía, y tal vez haga que el constructor sea privado para que siempre tenga que construir desde la lista vacía.fuente
Cada vez que estoy en un atasco con la nomenclatura, golpeo las interwebs.
thesaurus.com devuelve esto para "agregar":
Me gusta el sonido de
Adjoin
, o más simplementeJoin
. Eso es lo que estás haciendo, ¿verdad? El método también podría aplicarse para unirse a otrosImmutableList<>
.fuente
Personalmente, me gusta .With (). Si estaba usando el objeto, después de leer la documentación o los comentarios del código, sería claro lo que hace, y se lee bien en el código fuente.
O bien, agregue "Along" con él .. :)
fuente
Terminé yendo con Agregar para todas mis colecciones inmutables en BclExtras . La razón es que es un nombre fácil de predecir. No me preocupan tanto las personas que confunden Add con un add mutante, ya que el nombre del tipo tiene el prefijo Immutable.
Por un tiempo consideré Cons y otros nombres de estilo funcional. Finalmente los descarté porque no son tan conocidos. Claro que los programadores funcionales lo entenderán, pero no son la mayoría de los usuarios.
Otros nombres: usted mencionó:
Opciones que consideré:
Lamentablemente, en realidad no parece haber una palabra que sea
Se vuelve aún más extraño cuando considera colecciones distintas a la Lista. Tomemos por ejemplo Stack. Incluso los programadores de primer año pueden decirle que las pilas tienen un par de métodos Push / Pop. Si crea un ImmutableStack y le da un nombre completamente diferente, llamémoslo Foo / Fop, acaba de agregar más trabajo para que puedan usar su colección.
Editar: Respuesta a Plus Editar
Veo a dónde vas con Plus. Creo que un caso más fuerte sería en realidad menos para eliminar. Si veía lo siguiente, sin duda me preguntaría qué demonios estaba pensando el programador.
El mayor problema que tengo con Plus / Minus o un nuevo emparejamiento es que parece excesivo. La colección en sí ya tiene un nombre distintivo, el prefijo Inmutable. ¿Por qué ir más allá agregando vocabulario cuya intención es agregar la misma distinción que el prefijo Inmutable?
Puedo ver el argumento del sitio de la llamada. Lo aclara desde el punto de vista de una sola expresión. Pero en el contexto de toda la función parece innecesario.
Editar 2
De acuerdo en que la gente definitivamente ha sido confundida por String.Concat y DateTime.Add. He visto a varios programadores muy brillantes resolver este problema.
Sin embargo, creo que ImmutableList es un argumento diferente. No hay nada sobre String o DateTime que lo establezca como Inmutable para un programador. Simplemente debe saber que es inmutable a través de alguna otra fuente. Entonces la confusión no es inesperada.
ImmutableList no tiene ese problema porque el nombre define su comportamiento. Se podría argumentar que la gente no sabe lo que es Inmutable y creo que eso también es válido. Ciertamente no lo supe hasta aproximadamente el año 2 en la universidad. Pero tiene el mismo problema con el nombre que elija en lugar de Agregar.
Edición 3: ¿Qué pasa con los tipos como TestSuite que son inmutables pero no contienen la palabra?
Creo que esto lleva a casa la idea de que no deberías estar inventando nuevos nombres de métodos. Principalmente porque claramente existe un impulso para hacer que los tipos sean inmutables a fin de facilitar las operaciones paralelas. Si se enfoca en cambiar el nombre de los métodos para las colecciones, el siguiente paso serán los nombres de los métodos de mutación en cada tipo que use que sea inmutable.
Creo que sería un esfuerzo más valioso centrarse en hacer que los tipos sean identificables como inmutables. De esa manera, puede resolver el problema sin repensar cada patrón de método de mutación.
Ahora, ¿cómo puede identificar TestSuite como inmutable? En el entorno actual, creo que hay algunas maneras
Mi conjetura / esperanza es que las herramientas de desarrollo comenzarán a ayudar a este problema al facilitar la identificación de tipos inmutables simplemente a simple vista (color diferente, fuente más fuerte, etc.). Pero creo que esa es la respuesta sobre cambiar todos los nombres de métodos.
fuente
Creo que esta puede ser una de esas situaciones raras en las que es aceptable sobrecargar al
+
operador. En terminología matemática, sabemos que+
no agrega algo al final de otra cosa. Siempre combina dos valores y devuelve un nuevo valor resultante.Por ejemplo, es intuitivamente obvio que cuando dices
El valor resultante de x es 4, no 22.
Similar,
debería dejar en claro qué va a contener cada variable. Debe quedar claro que
list2
no se cambia en la última línea, sino quelist3
se le asigna el resultado de agregar "palabra" alist2
.De lo contrario, simplemente nombraría la función Plus ().
fuente
[1] + 2 = [1,2]
pero[1] + [2] = [1,[2]]
. Lo que estás sugiriendo es un comportamiento inconsistente. Esta es probablemente la razón por la cual Python no le permite agregar un elemento de esta manera.Para ser lo más claro posible, es posible que desee ir con la palabra
CopyAndAdd
, o algo similar.fuente
Lo llamaría Extend () o tal vez ExtendWith () si te sientes realmente detallado.
Extender significa agregar algo a otra cosa sin cambiarlo. Creo que esta es una terminología muy relevante en C # ya que es similar al concepto de métodos de extensión: "agregan" un nuevo método a una clase sin "tocar" la clase en sí.
De lo contrario, si realmente desea enfatizar que no modifica el objeto original en absoluto, usar algún prefijo como Get- me parece inevitable.
fuente
Agregado (), Agregado ()
Me gusta usar el tiempo pasado para operaciones en objetos inmutables. Transmite la idea de que no está cambiando el objeto original, y es fácil de reconocer cuando lo ve.
Además, debido a que los nombres de métodos de mutación a menudo son verbos en tiempo presente, se aplica a la mayoría de los casos necesarios de nombre de método inmutable con los que se encuentra. Por ejemplo, una pila inmutable tiene los métodos "empujado" y "reventado".
fuente
Me gusta la sugerencia de mmyers de CopyAndAdd . De acuerdo con un tema de "mutación", ¿tal vez podrías elegir Bud (reproducción asexual), Grow , Replicate o Evolve ? =)
EDITAR: Para continuar con mi tema genético, ¿qué tal Procreate , lo que implica que se crea un nuevo objeto que se basa en el anterior, pero con algo nuevo agregado.
fuente
Probablemente sea una exageración, pero en Ruby hay una notación de uso común para la distinción:
add
no muta;add!
mutantes Si este es un problema generalizado en su proyecto, también podría hacerlo (no necesariamente con caracteres no alfabéticos, sino que utiliza una notación para indicar métodos mutantes / no mutantes).fuente
Join
Parece apropiadofuente
Tal vez la confusión se deba al hecho de que desea dos operaciones en una. ¿Por qué no separarlos? Estilo DSL:
Copy
devolvería un objeto intermedio, que es una copia mutable de la lista original.With
devolvería una nueva lista inmutable.Actualizar:
Pero, tener una colección intermedia y mutable no es un buen enfoque. El objeto intermedio debe estar contenido en la
Copy
operación:Ahora, la
Copy
operación toma un delegado, que recibe una lista mutable, para que pueda controlar el resultado de la copia. Puede hacer mucho más que agregar un elemento, como eliminar elementos u ordenar la lista. También se puede usar en elImmutableList
constructor para ensamblar la lista inicial sin listas inmutables intermedias.Ahora no hay posibilidad de que los usuarios malinterpreten, naturalmente caerán en el pozo del éxito .
Otra actualización más:
Si todavía no le gusta la mención de la lista mutable, incluso ahora que está contenida, puede diseñar un objeto de especificación, que especificará , o script , cómo la operación de copia transformará su lista. El uso será el mismo:
Ahora puede ser creativo con los nombres de las reglas y solo puede exponer la funcionalidad que desea
Copy
admitir, no todas las capacidades de unIList
.Para el uso de encadenamiento, puede crear un constructor razonable (que no utilizará el encadenamiento, por supuesto):
O use el mismo delegado en otro constructor:
Esto supone que el
rules.Append
método vuelvethis
.Así es como se vería con su último ejemplo:
fuente
Algunos pensamientos al azar:
fuente
DateTime en C # utiliza Agregar. Entonces, ¿por qué no usar el mismo nombre? Mientras los usuarios de su clase entiendan que la clase es inmutable.
fuente
Creo que la clave a la que estás tratando de llegar y que es difícil de expresar es la no permutación, así que tal vez algo con una palabra generativa, algo como CopyWith () o InstancePlus ().
fuente
No creo que el idioma inglés le permita implicar la inmutabilidad de una manera inconfundible mientras usa un verbo que significa lo mismo que "Agregar". "Plus" casi lo hace, pero la gente aún puede cometer el error.
La única forma de evitar que los usuarios confundan el objeto con algo mutable es haciéndolo explícito, ya sea a través del nombre del objeto en sí o mediante el nombre del método (como con las opciones detalladas como "GetCopyWith" o "CopyAndAdd").
Así que ve con tu favorito, "Plus".
fuente
Primero, un punto de partida interesante: http://en.wikipedia.org/wiki/Naming_conventions_(programming) ... En particular, verifique los enlaces "Ver también" en la parte inferior.
Estoy a favor de Plus o And, efectivamente por igual.
Plus y And están basados en matemáticas en etimología. Como tal, ambos connotan operación matemática; ambos producen una expresión que se lee naturalmente como expresiones que pueden resolverse en un valor, que se ajusta al método que tiene un valor de retorno.
And
lleva una connotación lógica adicional, pero ambas palabras se aplican intuitivamente a las listas.Add
connota la acción realizada en un objeto, que entra en conflicto con la semántica inmutable del método.Ambos son cortos, lo cual es especialmente importante dada la primitividad de la operación. Las operaciones simples y realizadas con frecuencia merecen nombres más cortos.
Expresar la semántica inmutable es algo que prefiero hacer a través del contexto. Es decir, prefiero simplemente implicar que todo este bloque de código tiene una sensación funcional; Supongamos que todo es inmutable. Eso podría ser solo yo, sin embargo. Prefiero la inmutabilidad como regla; si se hace, se hace mucho en el mismo lugar; La mutabilidad es la excepción.
fuente
¿Qué tal Chain () o Attach ()?
fuente
visualthesaurus.com
(sin afiliación) cuando busquéconcatenate
.Prefiero más (y menos). Son fácilmente comprensibles y se asignan directamente a operaciones que involucran tipos inmutables bien conocidos (los números). 2 + 2 no cambia el valor de 2, devuelve un nuevo valor, igualmente inmutable.
Algunas otras posibilidades:
Empalme()
Injerto()
Juntar a()
fuente
¿Qué hay de mate , mateWith o coito , para aquellos que acatan? En términos de reproducción, los mamíferos generalmente se consideran inmutables.
Voy a echar a Union por ahí también. Prestado de SQL.
fuente
Aparentemente soy la primera persona de Obj-C / Cocoa en responder esta pregunta.
No voy a ganar ningún código de juegos de golf con esto.
fuente
[object]By[Verb]ing[Object]:
prefijo al método implica que se devolverá una nueva cadena en lugar de simplemente[verb][Object]:
, lo que mutaría el objeto en su lugar.Creo que "Agregar" o "Más" suena bien. El nombre de la lista en sí debería ser suficiente para transmitir la inmutabilidad de la lista.
fuente
Tal vez hay algunas palabras que me recuerdan más de hacer una copia y agregar cosas a eso en lugar de mutar la instancia (como "Concatenar"). Pero creo que tener algo de simetría para esas palabras para otras acciones también sería bueno. No sé de una palabra similar para "Eliminar" que pienso del mismo tipo como "Concatenar". "Plus" me suena un poco extraño. No esperaría que se usara en un contexto no numérico. Pero eso también podría provenir de mi origen no inglés.
Tal vez usaría este esquema
Sin embargo, estos tienen sus propios problemas, cuando lo pienso. Uno podría pensar que eliminan algo o agregan algo a un argumento dado. No estoy seguro de eso en absoluto. Esas palabras tampoco son buenas para encadenar, creo. Demasiado prolijo para escribir.
Tal vez usaría simplemente "Agregar" y amigos también. Me gusta como se usa en matematicas
Bueno, ciertamente, un 2 sigue siendo un 2 y obtienes un nuevo número. Se trata de dos números y no de una lista y un elemento, pero creo que tiene alguna analogía. En mi opinión,
add
no necesariamente significa que mutas algo. Ciertamente veo su punto de vista de que tener una declaración solitaria que contenga solo unadd
y no use el nuevo objeto devuelto no parece tener errores. Pero ahora también he pensado alguna vez en la idea de usar otro nombre que no sea "agregar", pero no puedo encontrar otro nombre, sin hacerme pensar "hmm, tendría que mirar la documentación para saber qué se trata de "porque su nombre difiere de lo que esperaría que se llamara" agregar ". Solo un pensamiento extraño sobre esto de litb, no estoy seguro de que tenga sentido en absoluto :)fuente
Mirando http://thesaurus.reference.com/browse/add y http://thesaurus.reference.com/browse/plus encontré ganancia y fijación, pero no estoy seguro de cuánto implican no mutación.
fuente
Creo que
Plus()
yMinus()
o, alternativamente,Including()
,Excluding()
son razonables en lo que implica el comportamiento inmutable.Sin embargo, ninguna elección de nombres lo dejará perfectamente claro para todos, por lo que personalmente creo que un buen comentario de documento xml sería muy útil aquí. VS arroja esto directamente a su cara cuando escribe código en el IDE; son difíciles de ignorar.
fuente
Append
- porque, tenga en cuenta que los nombres de losSystem.String
métodos sugieren que mutan la instancia, pero no lo hacen.O me gusta bastante
AfterAppending
:fuente
list.CopyWith(element)
Al igual que Smalltalk :)
Y también
list.copyWithout(element)
eso elimina todas las apariciones de un elemento, lo cual es más útil cuando se usalist.copyWithout(null)
para eliminar elementos no definidos.fuente
Iría por Agregar, porque puedo ver el beneficio de un mejor nombre, pero el problema sería encontrar nombres diferentes para cada otra operación inmutable que podría hacer que la clase no sea familiar si eso tiene sentido.
fuente