Perché il segno meno, '-', generalmente non è sovraccaricato allo stesso modo del segno più?

64

Il segno più + viene utilizzato per l'addizione e per la concatenazione di stringhe, ma il suo compagno: il segno meno, - , non è generalmente visto per il taglio di stringhe o qualche altro caso diverso dalla sottrazione. Quale potrebbe essere la ragione o le limitazioni per questo?

Considera il seguente esempio in JavaScript:

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

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

6 risposte

117

In breve, non ci sono operazioni di sottrazione particolarmente utili sulle stringhe con cui le persone hanno voluto scrivere algoritmi.

L'operatore + indica in generale il funzionamento di un additivo monoid , cioè un'operazione associativa con un'identità elemento:

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

Ha senso usare questo operatore per cose come l'aggiunta di interi, la concatenazione di stringhe e l'unione dei set perché hanno tutti la stessa struttura algebrica:

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

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

E possiamo usarlo per scrivere algoritmi pratici come una funzione concat che funziona su una sequenza di elementi "concatenabili", ad esempio:

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

Quando la sottrazione - viene coinvolta, di solito parli della struttura di un gruppo , che aggiunge un inverso -A per ogni elemento A, in modo che:

  • A + -A = -A + A = 0

E mentre questo ha senso per cose come la sottrazione a virgola mobile e in virgola mobile, o anche impostare la differenza, non ha molto senso per le stringhe e le liste. Qual è l'inverso di "foo" ?

C'è una struttura chiamata monoid annullativo , che non ha inversioni, ma ha cancellazione proprietà, in modo che:

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

Questa è la struttura che descrivi, dove "ab" - "b" == "a" , ma "ab" - "c" non è definita. È solo che non abbiamo molti algoritmi utili che usano questa struttura. Suppongo che se si pensa alla concatenazione come serializzazione, la sottrazione potrebbe essere utilizzata per qualche tipo di analisi.

    
risposta data 28.10.2015 - 22:11
fonte
38

Perché la concatenazione di due stringhe valide è sempre un'operazione valida, ma il contrario non è vero.

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

Che cosa dovrebbe essere a - b qui? Non c'è davvero un buon modo per rispondere a questa domanda, perché la domanda in sé non è valida.

    
risposta data 28.10.2015 - 19:56
fonte
28

Perché l'operatore - per la manipolazione delle stringhe non ha abbastanza "coesione semantica". Gli operatori dovrebbero essere sovraccaricati solo quando è assolutamente chiaro che cosa fa il sovraccarico con i suoi operandi e la sottrazione di stringhe non soddisfa quella barra.

Di conseguenza, le chiamate ai metodi sono preferite:

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

Nel linguaggio C #, usiamo + per la concatenazione di stringhe perché il modulo

var result = string1 + string2 + string3;

invece di

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

è comodo e probabilmente più facile da leggere, anche se una chiamata di funzione è probabilmente più "corretta", da un punto di vista semantico.

L'operatore + può significare solo una cosa in questo contesto. Questo non è vero per - , poiché la nozione di sottrazione di stringhe è ambigua (la chiamata di funzione Replace(source, oldValue, newValue) con "" come il parametro newValue rimuove tutti i dubbi e la funzione può essere utilizzata per modificare le sottostringhe, non solo rimuoverli).

Il problema, ovviamente, è che il sovraccarico dell'operatore dipende dai tipi trasmessi all'operatore e se si passa una stringa in cui dovrebbe essere stato un numero, si può ottenere un risultato che non si aspettava. Inoltre, per molte concatenazioni (ad esempio in un ciclo), è preferibile un oggetto StringBuilder , poiché ogni utilizzo di + crea una nuova stringa e le prestazioni possono risentirne. Quindi l'operatore + non è nemmeno appropriato in tutti i contesti.

Esistono sovraccarichi dell'operatore con una coesione semantica migliore rispetto all'operatore + per la concatenazione di stringhe. Ecco uno che aggiunge due numeri complessi:

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

La lingua di Groovy non consente - :

println('ABC'-'B')

restituisce:

AC

E

println( 'Hello' - 'World' )

restituisce:

Hello

E:

println('ABABABABAB' - 'B')

restituisce:

AABABABAB
    
risposta data 29.10.2015 - 11:39
fonte
6

Il segno più probabilmente contestualmente ha senso in più casi, ma un contro-esempio (forse un'eccezione che conferma la regola) in Python è l'oggetto set, che fornisce - ma non + :

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

Non ha senso usare il segno + perché l'intenzione potrebbe essere ambigua - significa intersezione o unione? Invece, utilizza | per unione e & per intersezione:

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

" - " è usato in alcune parole composte (per esempio "on-site") per unire le diverse parti nella stessa parola. Perché non usiamo " - " per unire insieme stringhe diverse nei linguaggi di programmazione? Penso che sarebbe perfettamente sensato! Al diavolo con questo + nonsense!

Tuttavia, proviamo a guardare questo da un angolo un po 'più astratto.

Come definiresti l'algebra delle stringhe? Quali operazioni vorresti avere e quali leggi potrebbero valere per loro? Quali sarebbero le loro relazioni?

Ricorda, non ci può essere assolutamente nessuna ambiguità! Ogni caso possibile deve essere ben definito, anche se vuol dire che non è possibile farlo! Più piccola è la tua algebra, più facile è questo.

Ad esempio, cosa significa in realtà aggiungere o sottrarre due stringhe?

Se aggiungi due stringhe (ad esempio, lascia a = "aa" e b = "bb" ), otterrai aabb come risultato di a + b ?

Che ne dici di b + a ? Sarebbe bbaa ? Perché non aabb ? Cosa succede se sottrai aa dal risultato della tua aggiunta? La tua stringa ha un concetto di importo negativo di aa in esso?

Ora torna all'inizio di questa risposta e sostituisci spaceshuttle invece della stringa. Per generalizzare, perché ogni operazione è definita o non definita per alcun tipo?

Il punto che sto cercando di fare è che non c'è nulla che ti impedisca di creare un'algebra per qualcosa. Potrebbe essere difficile trovare operazioni significative o anche operazioni utili per questo.

Per le stringhe, concatenare è praticamente l'unico sensato che abbia mai incontrato. Non importa quale simbolo viene utilizzato per rappresentare l'operazione.

    
risposta data 28.10.2015 - 20:34
fonte

Leggi altre domande sui tag