Desculpe pelo título waffly - se eu pudesse criar um título conciso, não precisaria fazer a pergunta.
Suponha que eu tenha um tipo de lista imutável. Possui uma operação Foo(x)
que retorna uma nova lista imutável com o argumento especificado como um elemento extra no final. Então, para criar uma lista de strings com os valores "Hello", "immutable", "world", você pode escrever:
var empty = new ImmutableList<string>();
var list1 = empty.Foo("Hello");
var list2 = list1.Foo("immutable");
var list3 = list2.Foo("word");
(Este é um código C #, e eu estou mais interessado em uma sugestão de C # se você achar que o idioma é importante. Não é fundamentalmente uma questão de idioma, mas os idiomas do idioma podem ser importantes.)
O importante é que as listas existentes não sejam alteradas por Foo
- portanto empty.Count
, ainda retornaria 0.
Outra maneira (mais idiomática) de chegar ao resultado final seria:
var list = new ImmutableList<string>().Foo("Hello")
.Foo("immutable")
.Foo("word");
Minha pergunta é: qual é o melhor nome para Foo?
EDIÇÃO 3 : Como revelo mais adiante, o nome do tipo pode não ser realmente ImmutableList<T>
, o que torna a posição clara. Imagine, ao contrário, que é TestSuite
e é imutável, porque toda a estrutura da qual faz parte é imutável ...
(Fim da edição 3)
Opções que eu vim até agora:
Add
: comum no .NET, mas implica em mutação da lista originalCons
: Acredito que esse seja o nome normal nas linguagens funcionais, mas sem sentido para quem não tem experiência nessas linguagensPlus
: meu favorito até agora, não implica mutação para mim . Aparentemente, isso também é usado no Haskell, mas com expectativas ligeiramente diferentes (um programador do Haskell pode esperar que ele adicione duas listas juntas em vez de adicionar um único valor à outra lista).With
: consistente com algumas outras convenções imutáveis, mas não possui a mesma "adição" à IMO.And
: não muito descritivo.- Sobrecarga de operador para +: eu realmente não gosto muito disso; Em geral, acho que os operadores devem ser aplicados apenas aos tipos de nível inferior. Estou disposto a ser persuadido!
Os critérios que estou usando para escolher são:
- Dá a impressão correta do resultado da chamada do método (ou seja, é a lista original com um elemento extra)
- Torna o mais claro possível que não altera a lista existente
- Parece razoável quando encadeados, como no segundo exemplo acima
Por favor, peça mais detalhes se eu não estiver me esclarecendo o suficiente ...
EDIT 1: Aqui está meu raciocínio para preferir Plus
a Add
. Considere estas duas linhas de código:
list.Add(foo);
list.Plus(foo);
Na minha opinião (e isso é uma coisa pessoal), o último é claramente buggy - é como escrever "x + 5;" como uma declaração por si só. A primeira linha parece estar correta, até você lembrar que é imutável. De fato, a maneira como o operador plus por si só não muda seus operandos é outra razão pela qual Plus
é o meu favorito. Sem a ligeira repugnância da sobrecarga do operador, ela ainda fornece as mesmas conotações, que incluem (para mim) não alterar os operandos (ou o destino do método neste caso).
EDIT 2: Motivos para não gostar Adicionar.
Várias respostas são efetivamente: "Vá com Add. É isso que DateTime
faz, e String
tem Replace
métodos etc. que não tornam a imutabilidade óbvia". Eu concordo - há precedência aqui. No entanto, tenho visto muitas pessoas chamam DateTime.Add
ou String.Replace
e esperar mutação . Há muitas perguntas de grupos de notícias (e provavelmente SO, se eu procurar) que são respondidas por "Você está ignorando o valor de retorno String.Replace
; strings são imutáveis, uma nova string é retornada".
Agora, devo revelar uma sutileza à pergunta - o tipo pode não ser realmente uma lista imutável, mas um tipo imutável diferente. Em particular, estou trabalhando em uma estrutura de benchmarking em que você adiciona testes a um conjunto e isso cria um novo conjunto. Pode ser óbvio que:
var list = new ImmutableList<string>();
list.Add("foo");
não vai conseguir nada, mas fica muito mais obscuro quando você o altera para:
var suite = new TestSuite<string, int>();
suite.Add(x => x.Length);
Parece que tudo ficará bem. Enquanto isso, para mim, torna o erro mais claro:
var suite = new TestSuite<string, int>();
suite.Plus(x => x.Length);
Isso está apenas implorando para ser:
var suite = new TestSuite<string, int>().Plus(x => x.Length);
Idealmente, eu gostaria que meus usuários não precisassem saber que o conjunto de testes é imutável. Eu quero que eles caiam no poço do sucesso. Isso pode não ser possível, mas eu gostaria de tentar.
Peço desculpas por simplificar demais a pergunta original falando apenas sobre um tipo de lista imutável. Nem todas as coleções são tão auto-descritivas quanto ImmutableList<T>
:)