On Feb 6, 2010, at 11:46 PM, Pietro Battiston wrote: > Il punto che forse non è chiaro è cosa sia l'aritmetica.
Sarebbe da capire a chi non è chiaro cosa sia. Sono abbastanza sicuro di non essere io quello con dubbi o lacune. Qui si sta parlando di aritmetica mista fra interi e booleani. Che a te da fastidio, a me e a Guido no. Quello che io ho scritto è semplicemente che *se* vuoi aritmetica che coinvolga anche i booleani di fatto la cosa più naturale è che False sia equivalente a 0 e True ad 1, al di la del fatto che bool is-a int per l'implementazione corrente. Se poi bandisci tale aritmetica hai semplicemente un linguaggio decisamente meno comodo senza essenzialmente nessun vantaggio concreto. > Sia dal punto di vista matematico che da quello del Python, "==" è > qualcosa che non ha _niente_ a che fare con l'aritmetica: dal punto di > vista logico-matematico perché l'eguaglianza non è (necessariamente) un > operatore, dal punto di vista di come ragiona il Python perché "==" può > confrontare due oggetti qualsiasi, non solo numerici. Diventa > l'uguaglianza tra numeri... esattamente quando gli argomenti sono due > numeri. 1. Da un punto di vista matematico il predicato = (che da pythonisti chiamiamo ==) ha *tantissimo* a che fare con l'aritmetica stessa. Non so se hai fatto un minimo di fondamenti, ma fra gli assiomi di peano ci sono precisamente quelli che riguardano =, senza non fondi l'aritmetica sulla set theory. Puoi fondarla sulla logica combinatoria, ma ovviamente stiamo spostandoci alquanto. 2. Dal punto di vista "matematico" un operatore come il == è una bestiaccia. Immagino tu non abbia lavorato più di tanto (suppongo nulla) sulla semantica formale dei linguaggi di programmazione. Formalizzare un linguaggio ad oggetti è abbastanza un bagno di sangue (fidati, è un bagno di sangue anche avere un linguaggetto come C). Formalizzare qualcosa come Python è essenzialmente un suicidio. La semantica denotazionale è essenzialmente inadatta. Io avevo lavorato parecchio con structured operational semantics, che funzionerebbe anche decentemente... ma il dinamismo di Python sarebbe una iattura. Quindi, tiriamo fuori la matematica dal discorso. O le cose si fanno bene, e ti garantisco che quando si va sul formale divento *davvero* sgradevolmente pignolo, oppure la tiriamo indietro. Ma fino in fondo. Quindi rimaniamo al problema fondamentale: stiamo cercando di avere booleani che si comportano come gli interi. Se no, devi proibire le commistioni. Ed essenzialmente hai un altro linguaggio, che non è Python, che è più scomodo di Python e che, per coerenza, deve andare contro molte convenzioni ed idiomi pythonici. Già... se ci troviamo if 0: print "ciao" -> ciao mi aspetto anche if []: print "ciao" -> ciao e per risolvere la cosa... if bool([])? Fa schifo. Allora tanto vale prendersi if len([]) == 0: che è un tipico idioma anti-pythonico, sconsigliato a tutti i niubbi. > Stai scherzando?! Questo punto è stato chiarito 5 mail fa. > _Evidentemente_ bool(0) == False. Nope. Tu parti dal presupposto che i bool e gli int debbano essere tipi distinti. E guarda caso concludi che debbano essere tipi distinti. Il che porta un po' a quello che veramente è stato detto alcune mail fa. Ovvero che di per se puoi benissimo tirare un'eccezione ogni volta che mischi interi e booleani. Ma *non* è quello che vuole Guido. Per inciso continuo a non vedere il vantaggio di farlo in Python. E a quel punto mi aspetto anche che l'inferno si scateni quando mischio float e interi. >> Comunque davvero, la cosa più naturale è vedere True e False come numeri a >> 1-bit. > > Non dubito che per te possa essere (ormai?) naturale... Ormai? Non so. Non vedo perchè un numero di un bit non debba essere un numero. Ah, tu dici che non è un numero. Ok. Un numero di due bit è un numero? No? Uno di 31? No? uno di 32? Si. Ah, ok. >> Non ci formalizziamo perchè 0 == 0L, ma ci da fastidio False. > > ... ma renditi conto che questo è un argomento che non c'entra niente. Come non centra niente? 0L è lo 0 dei long, 0 degli int, False dei bool. Caso che mai non ti fosse sfuggito, long e int sono tipi *diversi* in Python. Eppure non ti stupisci che lo 0 dei long sia diverso dallo 0 degli interi. Per non parlare dello 0 dei float e quello degli interi. > Tutti i tipi numerici hanno somma, sottrazione, moltiplicazione, > divisione (questa, con qualche distinguo), che definiscono su di essi > delle immersioni che sono più che canoniche, sono _ovvie_: i naturali > (chiusi solo per la somma) sono degli interi (chiusi per somma, > sottrazione, prodotto), che sono dei razionali (OK, questi l'informatica > per quanto ne so ce li risparmia), che sono dei reali (chiusi per tutte > le operazioni - tralasciando la rappresentazione approssimata), che > volendo sono dei complessi. Ti mancano un sacco di pezzi, mi dispiace. Di fatto ti aspetti erroneamente che i tipi numerici in macchina si comportino come quelli della matematica. In primo luogo "l'informatica" non ci risparmia affatto i razionali. In scheme per esempio sono abbastanza standard (anzi, sarebbero nello standard). Python stesso li implementa in una libreria standard, sebbene da poco. Il tuo discorso purtroppo cade in quanto tu hai l'erronea convinzione che quello che hai studiato in algebra elementare debba valere su un computer. I reali non ci sono. E non ci possono essere. La dimostrazione è pure banale, quindi dimenticali. Quella che tu definisci "approssimazione" ha un piccolo problema: le operazioni che ci sono definite sopra *non* hanno le proprietà delle operazioni che hai sui reali. Tipicamente non hai nemmeno la proprietà associativa. Non sei manco in un semigruppo. Idem per gli interi. Gli interi (di C) *non* hanno proprietà associativa sull'addizione. Sono "fatti meglio" gli unsigned che hanno una buona aritmetica modulare. Ma finisce li la storia. In Python invece la somma non è nemmeno un operazione? Come come? Se sommi due interi, puoi ottenere un long. Ergo quella, matematicamente, non è un'operazione. Certo, è comodo. Ma appunto, abbandona quello che "dovrebbe essere". > In tutto ciò i booleani, che sono nati come logica a due valori in cui > le due operazioni "standard" erano or (l'equivalente intero è "max", non > una delle operazioni aritmetiche) e and ("min"), sono un caso a parte. > Ma non c'è solo problema storico: c'è che seppure l'addizione (così come > la sottrazione) assomiglia ad un'operazione logica, lo xor, purtroppo > l'insieme dei booleani _non è chiuso_ rispetto ad essa (dato che anche > assumendo che i booleani siano numeri, True + True non sarebbe un > booleano): ovvero non si comporta affatto come lo xor. Quindi _comunque_ > quando parliamo di addizione di booleani è piuttosto ipocrita spacciarla > per un'operazione "nativa": è, come tutti hanno ammesso, una comodissima > eredità del C. Non è un'operazione infatti. Esattamente come in Python non è un'operazione la somma. Come come? Dal momento che int è un tipo *limitato* quando fai somma di due interi, puoi sforare e quando succede: 1. dai eccezione 2. cambi tipo Il comportamento in Python è il secondo. Secondo le definizioni dell'aritmetica e dell'algebra elementare che io non dovrei sapere (rotfl) questa *non* è un'operazione. Un'operazione in senso matematico è la somma sugli unsigned (che infatti hanno esattamente il comportamento dell'aritmetica modulare). Non è un'operazione una cosa che ti tira un integer overflow e non è un'operazione una AxA -> B dove B non e' incluso in A. Infatti ti sei ben guardato da definire la sottrazione un'operazione sui naturali e la divisione un'operazione sugli interi. Ecco... la somma nemmeno lei è un'operazione. Questo se non vogliamo considerare l'estensione automatica del tipo. Apparentemente sommare due interi e ottenere automaticamente un long non ti infastidisce, sommare due booleani e ottenere un int si. Boh. BTW, non tirare in ballo xor e compagnia, al momento non hanno nulla a che vedere. Una volta ammessa sta somma fra interi che da un long, per quando mi riguarda ammetto anche la somma su booleani che mi da un int. Per inciso, le operazioni booleane sono facilmente estensibili agli interi come operazioni bit a bit. Quindi continuo a non vedere il problema. > D'altronde, vedila in un altro modo: se per te è perfettamente naturale > che i booleani siano semplicemente (un piccolo sottoinsieme degli) > interi, e ti sembra quindi naturale che siano _identici_ in tutto e per > tutto rispettivamente a 0 e 1, non ti sembrerebbe naturale anche che > > In [1]: isinstance(1,bool) > Out[1]: True > > ?! Solo se non avessi capito una pura fava di niente di progettazione ad oggetti e avessi invertito il vincolo di ereditarietà nella mia testa. Poi essere "identici" è una proprietà forte. In genere non mi interessa. Quello che mi interessa (e che è alla base della programmazione con linguaggi dinamici) è *si comporta come*. Oltretutto, quello che probabilmente ti sfugge è che se un animale è un cane, un cane non è un intero. Ergo se un booleano è un intero, un interno non è un booleano. E, in conclusione, quella dell'ereditarietà è solo una scorciatoia implementativa. Quello che Guido vuole e che i Pythonisti si aspettano è che i booleani si possano usare dove si possono usare gli interi. Punto e stop. Sarebbe meglio che un booleano non fosse un intero ma si comportasse come tale. Amen. > La scomoda verità è che se volessimo una cosa "pulita" con False != 0, > il modo giusto sarebbe che, come in C, False e True fossero > semplicemente _definiti_ individualmente come 0 e 1. Solo che il tipo > "bool" ci fa comodo... mentre la riga di codice che ho scritto sopra è > assolutamente inutile. No, la riga di sopra è utilissima a mostrare la confusione che hai in testa e che spero di riuscire a sciogliere nei prossimi post. Nella tua crociata contro if 0 non ti sei accorto di una cosa ben più drammatica. True e False, in Python, non sono letterali. Sono *variabili*. Come come? >>> True = False >>> if True: print "buh!" ... >>> Questo si che fa un po' cacare. Certo un pervertito che va a rinominare True si merita tutto il male che può capitargli. E siccome i Pythonisti sono tutti adulti e vaccinati, si fa conto che quella cosa lassù non venga mai fatta e che tanto se uno vuole fottere il sistema ci sono anche metodi più creativi. Poi, tanto per divertitci... la sotto secondo me il vero True viene semplicemente nascosto e non succede nulla di grave, tanto che un del riporta tutto a post. > Ciò detto, ho già scritto che in fondo me ne frega assai: è evidente > che, posto che Guido si è già espresso, tutto il thread è puramente > teorico. Considera anche questo... in Ruby false e nil sono gli unici valori veramente falsi. Ovviamente Ruby funziona e tutto... ma viene spesso elencato fra le cose contro-intuitive di Ruby. Non sono quindi convinto che la praticità di Python gioverebbe di questa scelta. _______________________________________________ Python mailing list Python@lists.python.it http://lists.python.it/mailman/listinfo/python