[Python] Qu

Enrico Franchi enrico.franchi a gmail.com
Dom 14 Feb 2010 12:26:37 CET


On Feb 14, 2010, at 11:38 AM, Pietro Battiston wrote:

>> Eh... poi ci troviamo con questo. Indichiamo con b un booleano, con n,m,...
>> un intero e con a qualcosa che puo' essere indifferentemente un booleano
>> o un intero. Il nostro obiettivo e' definire le operazioni su Bool U Int, rispettivamente
>> l'insieme dei booleani e degli interi. 
> 
> ... con Bool ⊂ Int ?

Dipende. Nel python attuale si, nel "tuo" python ovviamente no.

>> Normalmente ci aspettiamo che:
>> 
>> n + m - m == n
>> siamo d'accordo?
>> False + m - m != False
> No, è qui il punto, io mi rendo perfettamente conto che questo si
> perderebbe, ma non mi interessa, perché ... 
> ... perché una cosa così non la userei mai e poi mai

Questo poco importa. Mi spiego, il fatto che tu od io pensiamo che usare
una data feature del linguaggio (esplicitamente) non sia una buona idea,
e' irrilevante.

Di fatto quello che otteniamo e' che la nuova struttura algebrica, che abbiamo
voluto per togliere una piccola bruttura, e' un orrido. Permettermi ma trovarci
con una cosa che non e' manco un gruppo per togliere identita' fra False e 
0 mi sembra una cura peggiore del male.

Il fatto che tu consideri o meno quel codice sensato non toglie che sia
perfettamente valido e di conseguenza tutto il codice scritto assumendo
proprieta' ragionevoli come quelle la sopra diventa automaticamente *sbagliato*.


> : anche ammesso che
> dei valori di verità si possano _contare_ (sempre perché torna comodo),
> non li conto certamente con un booleano: prima che completamente
> antipythonico, è estremamente controintuitivo. A parlare in generale si
> rischia sempre, ma mi sento comunque di dire che _nessuno_ "conterebbe"
> davvero con un booleano: tutt'al più, quel che facciamo è contare _i_
> booleani - cosa che si fa benissimo semplicemente con la conversione al
> volo di False in 0 e True in 1.

Quando progetti un linguaggio non puoi dire... si, questa feature del linguaggio
e' sbagliata e porta ad assurdi, ma tanto nessuno vuole veramente usarla.
Perche' qualcuno che la usera' ci sara'. 

E ne verrebbero fuori thread ben peggiori di questo. Per togliere un "fastidio"
(avere due oggetti diversi con lo stesso comportamento) ci troviamo con tutta
la struttura matematica dei tipi interi a mare.


> Questo è un motivo per cui quanto scrivi sopra è ben lontano dallo
> scandalizzarmi. L'altro è che se veramente tu ritieni che
>   n + m - m == n
> sia una regola sacrosanta che anche i booleani dovrebbero rispettare,
> allora
> 
>   In [1]: a = 5
> 
>   In [2]: False + a - a
>   Out[2]: 0
> 
> per me è scandaloso. Io vorrei leggere "False". Poi tu mi dici che è la
> stessa cosa, ma io sono convinto sia questione di abitudine e non si
> finisce più...

Non ho parlato di "regole sacrosante". Tuttavia mi sembra ragionevole, no?
E' talmente poco sacrosanto che in C non me lo aspetto e non vale. Ma non
e' che sia una buona cosa, voglio dire. Non me lo aspetto nemmeno con i 
float. 

Ma visto che in Python abbiamo interi illimitati (essenzialmente), quella cosa
li posso aspettarmela. Il fatto di perderla mi infastidisce molto piu' di 0 == False.

Questa cosa poi non e' questione di "abitudine". Tu insisti su quello che stampa.
A me quello che stampa interessa veramente poco: mi interessa la semantica
della computazione. Da un lato ho una cosa stampata che mi piace poco,
dall'altra ho codice rotto. Per me non sono due cose sullo stesso piano.

> Pensa che per me invece è assurdo (anche se formalmente impeccabile) che
> tu continui a chiamare
>   (Bool U Int, +)
> una cosa che, finché parliamo matematicamente, è semplicemente
>   (Int, +)
> dato che per come la vedi tu Bool ⊂ Int...

Non e' per come la vedo io, e' per come la vede Python. Per inciso, ho tenuto
le cose distinte, perche' stiamo parlando di questo ipotetico nuovo Python con
le tue regole. E in questo Python quello che stiamo andando a fare e' definire
le operazioni in Bool U Int.

> Tu mi dici "ma non è giusto, i bool sono numeri come gli altri!".
> Io dico di no.

No. Qui la faccenda e' andata oltre. Se non vuoi che i booleani siano interi,
posso accettarlo. Allora ci saranno eccezioni esattamente come se sommi
stringhe ed interi. Come fa Ruby. Questo e' un comportamento coerente.
IMHO e' meno comodo, ma e' completamente sound e robusto.

Nel momento in cui decidiamo di dare semantica di somma ai booleani
(che tu vuoi) tiriamo fuori i problemi di cui sopra.

> E questa è una differenza di opinione che non ha giustificazioni
> formali: a seconda di come sei abituato a concepire il concetto di
> booleano, alcune cose ti sembrano più controintuitive di altre.

Io ti sto dicendo: ci sono due mondi. Uno assolutamente inattaccabile
(quello di Ruby) e uno piu' pragmatico che e' come fa Python. Nota,
se anche i bool in Python non *fossero* numeri, ma si comportassero
come numeri, 0 == False dovrebbe dare comunque True. 

Il mondo che tu proponi, e' quello in cui perdi praticamente tutte le 
proprieta' algebriche utili.

> Infatti, il "problema" a cui pensavo è proprio questo, per cui per
> tenere le cose pulite sarebbe più semplice che l'ordinamento tra Int e
> Bool come li penso io rimanesse un ordinamento dei tipi.
> 
> Ciò detto, se posti i bool come li vorrei io ed un tale ordinamento
> "stupido" poi qualcuno mi dicesse "il fatto che
>   False > -1
>   False < 1
> ma
>   False != 0
> sembri controintuitivo è un sacrificio che vale la pena fare per poter
> confrontare Int con Bool in modo interessante", io gli darei ragione.

Io temo che a questo punto sia proprio una tua fisima. Permetti, ma 
mi stai dicendo che sei addirittura disposto a sacrificare il principio
del terzo escluso, probabilmente a giocarti l'induzione ben fondata...

Tutto questo per non avere 0 == False. Ora io capisco che ti dia fastidio,
ma non voglio credere che non ti dia un fastidio pazzesco il fatto che in
nome di questo principio hai praticamente buttato a mare qualunque 
possibile intuizione matematica.

> Tecnicamente, == è certamente un'uguaglianza semantica, ma io sono
> convinto - il discorso sarebbe lungo e forse inutile - che lo scopo
> prefissato è sempre l'aderenza all'== sintattica che un programmatore ha
> in mente.

In un linguaggio ad oggetti, e' tutto semantico e non sintattico. Penso inevitabilmente.
Ma davvero, non possiamo parlare di cose "intuitive" quando accettiamo che

a < b, a > b ma non a == b.

Tra l'altro, sebbene in disuso abbiamo ancora la funzione cmp. Che ritornerebbe
-1 nel primo caso, 1 nel secondo e 0 nel terzo. Non so... cmp a sto punto dovrebbe
lanciare un'eccezione.



Io credo di avere detto tutto quello che ho da dire sull'argomento.  Riassumendo,
tu all'altare del False != 0 + aritmetica mista sei disposto a sacrificare:

1. strutture algebriche
2. proprieta' abbastanza intuitive
3. principio del terzo escluso
4. cmp e simili

Io ti dico che IMHO tutto questo e' il famoso assurdo completo di cui parlavo.
Se mi avessi detto che bandivi aritmetica mista, sarei stato assolutamente d'accordo.
Non mi sarebbe piaciuto, ma avresti sacrificato pragmatismo per purezza.
Si sarebbe solo potuto aprire un dibattito filosofico su quando il pragmatismo
deve battere la purezza, al di la dello zen di Python.

Credo che invece avere aritmetica mista "castrata" che rompe praticamente
tutte le altre proprieta' matematiche intuitive che non siano 0 != False sia una
cura davvero peggiore del male.





Maggiori informazioni sulla lista Python