¿Por qué el signo menos, '-', generalmente no está sobrecargado de la misma forma que el signo más?

64

El signo más + se usa para la adición y para la concatenación de cadenas, pero su compañero: el signo menos, - , generalmente no se ve para recortar cadenas o algún otro caso que no sea la resta. ¿Cuál podría ser la razón o las limitaciones para eso?

Considere el siguiente ejemplo en JavaScript:

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

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

6 respuestas

117

En resumen, no hay ninguna operación de resta muy útil en las cadenas con las que las personas han querido escribir algoritmos.

El operador + generalmente denota la operación de un monoide aditivo, es decir, una operación asociativa con una identidad elemento:

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

Tiene sentido usar este operador para cosas como la suma de enteros, la concatenación de cadenas y la unión de conjuntos porque todos tienen la misma estructura algebraica:

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

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

Y podemos usarlo para escribir algoritmos útiles como una función concat que funciona en una secuencia de cualquier cosa "concatenable", por ejemplo:

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

Cuando la resta - se involucra, usualmente se habla de la estructura de un grupo , que agrega un inverso −A para cada elemento A, de modo que:

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

Y si bien esto tiene sentido para cosas como la resta de enteros y puntos flotantes, o incluso la diferencia de conjuntos, no tiene mucho sentido para las cadenas y listas. ¿Cuál es el inverso de "foo" ?

Hay una estructura llamada cancellative monoid , que no tiene inversos, pero tiene el propiedad de cancelación , de modo que:

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

Esta es la estructura que describe, donde "ab" - "b" == "a" , pero "ab" - "c" no está definido. Es solo que no tenemos muchos algoritmos útiles que usen esta estructura. Supongo que si piensas en la concatenación como una serialización, la resta podría usarse para algún tipo de análisis.

    
respondido por el Jon Purdy 28.10.2015 - 22:11
38

Porque la concatenación de cualquiera de las dos cadenas válidas es siempre una operación válida, pero lo contrario no es cierto.

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

¿Qué debería ser a - b aquí? Realmente no hay una buena manera de responder a esa pregunta, porque la pregunta en sí no es válida.

    
respondido por el Mason Wheeler 28.10.2015 - 19:56
28

Porque el operador - para la manipulación de cadenas no tiene suficiente "cohesión semántica". Los operadores solo deben estar sobrecargados cuando esté absolutamente claro qué hace la sobrecarga con sus operandos, y la resta de cadenas no cumple con esa barra.

En consecuencia, se prefieren las llamadas a métodos:

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

En el lenguaje C #, usamos + para la concatenación de cadenas porque el formulario

var result = string1 + string2 + string3;

en lugar de

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

es conveniente y posiblemente más fácil de leer, aunque una llamada de función es probablemente más "correcta", desde un punto de vista semántico.

El operador + solo puede significar una cosa en este contexto. Esto no es tan cierto para - , ya que la noción de restar cadenas es ambigua (la función call Replace(source, oldValue, newValue) con "" , ya que el parámetro newValue elimina todas las dudas y la función se puede usar para alterar las subcadenas, no solo eliminarlos).

El problema, por supuesto, es que la sobrecarga del operador depende de los tipos que se le pasan al operador, y si pasa una cadena donde debería haber un número, puede obtener un resultado que no esperaba. Además, para muchas concatenaciones (es decir, en un bucle), es preferible un objeto StringBuilder , ya que cada uso de + crea una cadena completamente nueva, y el rendimiento puede verse afectado. Así que el operador + ni siquiera es apropiado en todos los contextos.

Hay sobrecargas de operadores que tienen mejor cohesión semántica que el operador + para la concatenación de cadenas. Aquí hay uno que agrega dos números complejos:

public static Complex operator +(Complex c1, Complex c2) 
{
    return new Complex(c1.real + c2.real, c1.imaginary + c2.imaginary);
}
    
respondido por el Robert Harvey 28.10.2015 - 21:09
8

El Groovy language permite - :

println('ABC'-'B')

devuelve:

AC

Y:

println( 'Hello' - 'World' )

devuelve:

Hello

Y:

println('ABABABABAB' - 'B')

devuelve:

AABABABAB
    
respondido por el Wim Deblauwe 29.10.2015 - 11:39
6

El signo más probablemente tenga sentido en el contexto en más casos, pero un contra-ejemplo (quizás una excepción que prueba la regla) en Python es el objeto establecido, que proporciona - pero no + :

>>> 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'

No tiene sentido usar el signo + porque la intención podría ser ambigua. ¿Significa establecer intersección o unión? En su lugar, utiliza | para la unión y & para la intersección:

>>> set('abc') | set('bcd')
set(['a', 'c', 'b', 'd'])
>>> set('abc') & set('bcd')
set(['c', 'b'])
    
respondido por el Aaron Hall 29.10.2015 - 02:32
3

" - " se usa en algunas palabras compuestas (por ejemplo, "en el sitio") para unir las diferentes partes en la misma palabra. ¿Por qué no usamos " - " para unir diferentes cadenas en lenguajes de programación? ¡Creo que tendría perfecto sentido! ¡Al diablo con este + de tonterías!

Sin embargo, intentemos ver esto desde un ángulo un poco más abstracto.

¿Cómo definirías el álgebra de cuerdas? ¿Qué operaciones tendrías y qué leyes tendrían para ellas? ¿Cuáles serían sus relaciones?

¡Recuerda, puede no haber absolutamente ninguna ambigüedad! Todos los casos posibles deben estar bien definidos, incluso si significa decir que no es posible hacer esto. Cuanto más pequeño sea tu álgebra, más fácil se hace esto.

Por ejemplo, ¿qué significa realmente sumar o restar dos cadenas?

Si agrega dos cadenas (por ejemplo, deje a = "aa" y b = "bb" ), ¿obtendría aabb como resultado de a + b ?

¿Qué tal b + a ? ¿Sería ese bbaa ? ¿Por qué no aabb ? ¿Qué sucede si restas aa del resultado de tu suma? ¿Tu cadena tendría un concepto de cantidad negativa de aa en ella?

Ahora vuelva al principio de esta respuesta y sustituya spaceshuttle en lugar de la cadena. Para generalizar, ¿por qué se define o no se define cualquier operación para cualquier tipo?

El punto que trato de señalar es que no hay nada que le impida crear un álgebra para nada. Puede ser difícil encontrar operaciones significativas, o incluso operaciones útiles para ello.

Para cadenas, la concatenación es prácticamente la única sensata que he encontrado. No importa qué símbolo se utiliza para representar la operación.

    
respondido por el Zavior 28.10.2015 - 20:34

Lea otras preguntas en las etiquetas