Por que o sinal de menos, '-', geralmente não é sobrecarregado da mesma forma que o sinal de mais?

64

O sinal de mais + é usado para adição e para concatenação de cadeias, mas seu complemento: o sinal de menos, - , geralmente não é visto para aparar strings ou outro caso diferente de subtração. Qual poderia ser o motivo ou limitações para isso?

Considere o seguinte exemplo em JavaScript:

var a = "abcdefg";
var b = "efg";

a-b == NaN
// but
a+b == "abcdefgefg"
    
por Digvijay Yadav 28.10.2015 / 19:47
fonte

6 respostas

117

Em suma, não há operações de subtração particularmente úteis em strings com as quais as pessoas desejem escrever algoritmos.

O operador + geralmente denota a operação de um aditivo monoid , ou seja, uma operação associativa com uma identidade elemento:

  • A + (B + C) = (A + B) + C
  • A + 0 = 0 + A = A

Faz sentido usar esse operador para coisas como adição de inteiros, concatenação de strings e união de conjuntos, porque todos eles têm a mesma estrutura algébrica:

1 + (2 + 3) == (1 + 2) + 3
1 + 0 == 0 + 1 == 1

"a" + ("b" + "c") == ("a" + "b") + "c"
"a" + "" == "" + "a" == "a"

E podemos usá-lo para escrever algoritmos úteis, como a função concat , que funciona em uma sequência de itens "concatenáveis", por exemplo:

def concat(sequence):
    return sequence.reduce(+, 0)

Quando a% de subtração- é envolvida, você costuma falar sobre a estrutura de um grupo , que adiciona um inverso −A para cada elemento A, de modo que:

  • A + −A = −A + A = 0

E, embora isso faça sentido para coisas como subtração de ponto flutuante e inteiro, ou até mesmo para definir a diferença, isso não faz muito sentido para cadeias de caracteres e listas. Qual é o inverso de "foo" ?

Existe uma estrutura chamada monoid cancelativa , que não tem inversos, mas tem o propriedade de cancelamento , de modo que:

  • A - A = 0
  • A - 0 = A
  • (A + B) - B = A

Esta é a estrutura que você descreve, onde "ab" - "b" == "a" , mas "ab" - "c" não está definido. É só que não temos muitos algoritmos úteis que usam essa estrutura. Eu acho que se você pensar em concatenação como serialização, então a subtração poderia ser usada para algum tipo de análise.

    
por 28.10.2015 / 22:11
fonte
38

Como a concatenação de quaisquer duas cadeias válidas é sempre uma operação válida, mas o oposto não é verdadeiro.

var a = "Hello";
var b = "World";

O que deve a - b estar aqui? Não há realmente uma boa maneira de responder a essa pergunta, porque a pergunta em si não é válida.

    
por 28.10.2015 / 19:56
fonte
28

Porque o operador - para manipulação de string não tem "coesão semântica" suficiente. Os operadores só devem ser sobrecarregados quando estiver absolutamente claro o que a sobrecarga faz com seus operandos, e a subtração de strings não atende a essa barra.

Consequentemente, as chamadas de método são preferidas:

public string Remove(string source, string toRemove)
public string Replace(string source, string oldValue, string newValue)

Na linguagem C #, usamos + para concatenação de strings porque o formulário

var result = string1 + string2 + string3;

em vez de

var result = string.Concat(string1, string2, string3);

é conveniente e possivelmente mais fácil de ler, mesmo que uma chamada de função seja provavelmente mais "correta", do ponto de vista semântico.

O operador + pode realmente significar apenas uma coisa neste contexto. Isso não é verdade para - , pois a noção de subtrair strings é ambígua (a chamada de função Replace(source, oldValue, newValue) with "" como o parâmetro newValue remove todas as dúvidas e a função pode ser usada para alterar substrings, não apenas removê-los).

O problema, é claro, é que a sobrecarga do operador depende dos tipos que estão sendo passados para o operador, e se você passar uma string onde deveria estar um número, você pode obter um resultado que você não esperava. Além disso, para muitas concatenações (por exemplo, em um loop), um objeto StringBuilder é preferível, pois cada uso de + cria uma nova sequência e o desempenho pode sofrer. Portanto, o operador + nem é apropriado em todos os contextos.

Existem sobrecargas de operador que possuem melhor coesão semântica do que o operador + para concatenação de cadeias de caracteres. Aqui está um que adiciona dois números complexos:

public static Complex operator +(Complex c1, Complex c2) 
{
    return new Complex(c1.real + c2.real, c1.imaginary + c2.imaginary);
}
    
por 28.10.2015 / 21:09
fonte
8

O idioma do Groovy permite - :

println('ABC'-'B')

retorna:

AC

E:

println( 'Hello' - 'World' )

retorna:

Hello

E:

println('ABABABABAB' - 'B')

retorna:

AABABABAB
    
por 29.10.2015 / 11:39
fonte
6

O sinal de mais provavelmente contextualmente faz sentido em mais casos, mas um contra-exemplo (talvez uma exceção que comprove a regra) em Python é o objeto set, que fornece - mas não + :

>>> set('abc') - set('bcd')
set(['a'])
>>> set('abc') + set('bcd')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unsupported operand type(s) for +: 'set' and 'set'

Não faz sentido usar o sinal + porque a intenção pode ser ambígua - significa interseção ou união? Em vez disso, ele usa | para união e & para interseção:

>>> set('abc') | set('bcd')
set(['a', 'c', 'b', 'd'])
>>> set('abc') & set('bcd')
set(['c', 'b'])
    
por 29.10.2015 / 02:32
fonte
3

" - " é usado em algumas palavras compostas (por exemplo, "no local") para unir as diferentes partes na mesma palavra. Por que não usamos " - " para unir strings diferentes em linguagens de programação? Eu acho que faria todo o sentido! Para o inferno com esse + absurdo!

No entanto, vamos tentar ver isso de um ângulo um pouco mais abstrato.

Como você definiria a álgebra de strings? Quais operações você teria e quais leis teriam para elas? Quais seriam as suas relações?

Lembre-se, pode não haver absolutamente nenhuma ambigüidade! Todos os casos possíveis devem ser bem definidos, mesmo que isso signifique dizer que não é possível fazer isso! Quanto menor sua álgebra, mais fácil isso é feito.

Por exemplo, o que significa adicionar ou subtrair duas strings?

Se você adicionar duas strings (por exemplo, let a = "aa" e b = "bb" ), você obterá aabb como resultado de a + b ?

Que tal b + a ? Isso seria bbaa ? Por que não aabb ? O que acontece se você subtrair aa do resultado da sua adição? Sua string teria um conceito de quantidade negativa de aa ?

Agora volte para o início desta resposta e substitua spaceshuttle em vez da string. Para generalizar, por que qualquer operação é definida ou não definida para qualquer tipo?

O ponto que estou tentando dizer é que não há nada que impeça você de criar uma álgebra para qualquer coisa. Pode ser difícil encontrar operações significativas ou até mesmo operações úteis para isso.

Para strings, concatenar é praticamente o único sensato que já encontrei. Não importa qual símbolo é usado para representar a operação.

    
por 28.10.2015 / 20:34
fonte