[Python] Qu

Pietro Battiston toobaz a email.it
Sab 13 Feb 2010 14:58:51 CET


Il giorno ven, 12/02/2010 alle 19.59 +0100, Enrico Franchi ha scritto:
> On Feb 11, 2010, at 12:24 AM, Pietro Battiston wrote:
> 
> > Quando si parla di vantaggi concreti, preferisco farlo davanti a dati
> > concreti.
> 
> Che sarebbero? 

Forse non ero chiaro: i vantaggi concreti di cui _tu_ parlavi non mi
sembravano supportati da fatti (a scanso di equivoci, ricordo che questa
discussione consiste in me che dico "mi sembrerebbe assolutamente
fattibile, anche se non necessariamente opportuno ora come ora" e te che
rispondi "è assolutamente infattibile").

> 
> > Ovviamente non intendevo che l'aritmetica possa esistere senza
> > uguaglianza, ma che il simbolo "=" può essere definito ben a monte
> > dell'aritmetica, in maniera vagamente simmetrica a quel che succede
> > appunto nel Python.
> 
> Probabilmente diamo dunque un differente significato al concetto di
> "non avere niente a che fare". Comunque una volta che siamo in accordo,
> tutto bene.
> 
> Poi ovviamente si, sono d'accordo che un uguaglianza possa stare a monte
> dell'aritmetica (uguaglianza semantica, intendo, l'uguaglianza sintattica e' una bestia
> ancora diversa).
> 
> Anche l'uguaglianza di python e', ovviamente potenzialmente semantica. Sebbene il default
> di object sia la versione ad oggetti dell'uguaglianza sintattica, ovvero la 
> completa identita', di fatto poi == e' ridefinito per vaste classi di oggetti. 
> Suppongo che su sta roba siamo tutti d'accordo e non
> sia necessario soffermarci oltre.

assolutamente

> 
> > Se le tue intuizioni informatiche sono azzeccate quanto quelle
> > personali, non mi stupisce la confusione che fai parlandone.
> 
> Ottimo. Allora ci hai lavorato anche tu e dovresti essere piuttosto consapevole
> del fatto che definire formalmente un metodo di un oggetto di un linguaggio
> completamente dinamico sia un lavoraccio, visto che hai la *semantica* che
> dipende dall'esecuzione, visto che quale codice venga chiamato da una data
> chiamata di funzione (o anche solo da un accesso a membro) e' potenzialmente
> non noto a compile time.
> 
> Anche immaginando un == scritto "staticamente" c' da fare un discreto lavoro
> per formalizzare il tutto. E non credo che la cosa ci porti da nessuna parte,
> ma se vuoi iniziare ti seguo e vediamo di metterla in piedi.
> 

... ma ti dirò di più: ero consapevolissimo di non dare né cercare una
formalizzazione completa, e pronto a risposte tipo "guarda, ti è
sfuggito questo particolare", vedi anche sotto. È solo che ho ricevuto
un altro tipo di risposte.


[snip della parte sulla polemica, che ora mi sembra stiamo evitando entrambi con successo]


> > La tua teoria secondo cui tutto deve necessariamente essere così com'è
> > si poteva (almeno, mi ero figurato che si potesse) motivare dal punto di
> > vista dell'eleganza matematica _o_ dell'attinenza alla mentalità
> > pythonesca: se tu dici che la matematica non c'entra niente, tirala pure
> > via, altrimenti vai fino in fondo e facciamo le cose "bene", la
> > precisione non è mai sgradevole.
> 
> Guarda, io sono una persona abbastanza pedante. Sono molto formale, a volte
> pure troppo. Il motivo per cui vorrei lasciare perdere l'eleganza matematica e' che
> spesso nel mondo pragmatico dei linguaggi di programmazione viene sacrificata
> in molti punti e modi ben peggiori di questo. Il che vuole dire che appellarsi troppo
> all'intuizione matematica non di rado porta fuori strada.
> 
> Di fatto sono pochissimi i linguaggi che non soffrono di questo problema, e a volte
> sono parecchio scomodi proprio per questa ragione.
> 

N.B: forse un po' di confusione nella discussione è causata dal fatto
che "motivare matematicamente" può voler dire
1) argomentare con l'analisi formale del linguaggio, ammesso (e
concesso) che la si consideri ancora "matematica"
2) argomentare con il fatto che se un programmatore, che è poi l'utente
del linguaggio, si trova ad utilizzare oggetti matematici - e.g. numeri
- dovranno comportarsi, per quanto possibile, come lui si aspetta.

A volte l'1 pone dei vincoli necessari al 2; ciononostante del Python mi
piace che pone molta attenzione al 2 (vedi passare automaticamente da
int a long, perché di nuovo, quando come programmatore penso a "int" in
Python penso agli interi, non agli interi modulo INT_MAX).



> Io poi non sostengo che tutto debba essere come e'. Non ho parlato di "tutto".
> Ti ho anche indicato un punto che trovo sgradevole (e che fortunatamente 
> hanno fixato in Python 3). Posso aggiungere che mi piacerebbe che Python potesse
> essere tail recursive (anche se so perche' non PUO' esserlo). Etc etc etc.

OK, scusa, intendevo "tutto" ciò che stavano discutendo.



> Se ho capito bene, tu vorresti 0 != da False *ma* avendo aritmetica mista. E questo
> IMHO non porta da nessuna parte. 
> 
> > Stai scherzando?! Questo punto è stato chiarito 6 mail fa.
> > _Evidentemente_
> > if 0: print "ciao" -> ...
> > if []: print "ciao" -> ...
> 
> 
> No, non sto scherzando. Continui a chiedermelo. Se stessi scherzando
> proverei con delle barzellette. Se scrivo su un gruppo tecnico, è probabile
> che non stia scherzando.
> 
> Probabilmente non ti piace il Python idiomatico.
> Utilizzare cose come
> 
> if len([]) == 0:
> 
> sono considerate *cattiva* pratica. Proporre di abbandonare la pratica
> considerata "buona" di
> 
> if []: 
> 
> IMHO non è particolarmente sensato.


Ma infatti non l'ho proposto, ed è la terza volta che cerco di
chiarirlo...


> > Non ne vedo affatto la ragione. Se dopo tutte queste mail ti sfugge
> > ancora la semantica che ho in mente, te la rispiego: il comportamento
> > dei bool rimane _ovunque_ quello che è, tranne che 0 != False (e
> > ovviamente ottieni risultati diversi se vai a vedere l'ereditarietà).
> 
> Mi sfugge perche' non mi sembrava scritto nero su bianco. Anzi, mi 
> sembra che altaleni fra NON ammettere l'aritmetica mista e ammetterla
> ma con 0 != da False.
> 

No, è sempre la seconda, chiarisco sotto.

> > Come si ottiene? Levando l'ereditarietà e ridefinendo gli operatori
> > necessari. Se c'è qualcosa di naif in questa idea di implementazione,
> > sono tutt'orecchi (occhi), ma se la semantica di per sé non fosse valida
> > forse gli "assurdi completi" che menzionavi varie mail fa sarebbero
> > ormai venuti alla luce.
> 
> Quindi spiegami meglio, tu proponi questa semantica.
> 
> 0 != False -> True
> 0 == False -> False

certo

> 
> Ora dimmi cosa vuoi fare in questi casi:
> 
> 10 * False  
> 10 + False 

il bool è convertito automaticamente in int ==> rispettivamente 0 e 10

> 0 < False
> 0 > False
> 0 < True
> 0 > True
> 

Per come l'ho sostenuta sinora, semplicemente l'ordering tra tipi
diversi, ovvero int > bool in python 2.*, eccezione in python 3.* (se
non sbaglio). Poi preferisco la prima, ma questo è un altro discorso.

> Ovviamente, se tiri delle eccezioni, torniamo a quello che dico io.
> La cosa che non capisco è: si continua a parlare di booleani che
> si comportano come interi. Tu la sopra dici
> 
> """il comportamento dei bool rimane _ovunque_ quello che è, tranne che 0 != False"""
> 
> Che va bene. Ergo posso assumere che tutte le operazioni di cui sopra
> abbiano il consueto risultato. Tranne, immagino, cose come 0 < False, che ovviamente
> cambiano. 

Sì. Non che veda niente di proibito in

int < bool
    definito come
int < int(bool)

, ma non stavo pensavo a quello (che poi potrebbe essere pure più
comodo, non so).

> 
> Per gli assurdi promessi, attendo le risposte alle domande di cui sopra.
> Piu' precisa mi dai la semantica piu' mi e' facile scriverli. Altrimenti devo fare
> molte assunzioni e per ogni scelta, essenzialmente, raddoppiare la dimostrazione.
> 
> 
> > Immagina pure, io più chiaro non potevo essere.
> 
> Quindi 0.0 == 0 o no?
> E 0L == 0 o no?[0]

Sìsì, certo.

Ma ti rendi conto che per nessuno di questi valori in Python si è
ritenuto necessario introdurre un nuovo letterale (o una variabile)? Ti
sembra veramente un caso?!

A me sembra un suggerimento, casomai ce ne fosse bisogno, del fatto che
il programmatore comune considera i bool prima come valori di verità e
solo in seguito come cose che possono "giocare" con/come i numeri.


> 
> ----
> [0] fintanto che ci sono i long, ma possiamo estendere il concetto
> a razionali e complessi e altri tipi numerici eventualmente definiti in seguito.
> 
> > Per me puoi chiamare "numero" anche una mela, se ti fa comodo, riesci a
> > infilarlo in un certo numero di bit e riesci ad infilarci qualche
> > operazione aritmetica.
> 
> No, davvero, ripeto. Di quanti bit hai bisogno per considerarlo numero? 

No, ho bisogno che sia un numero per considerarlo numero. Vorrei dire
"nella realtà", ma ovviamente mi farei ridere dietro: diciamo nella
mente del programmatore medio, quello per cui è stato deciso che
esistessero False e True, nonostante la loro attuale ridondanza rispetto
a 0 e 1.

> Perchè le operazioni da numero il booleano le ha, e non in modo più
> contraddittorio di quello che *oggi* siano fra interi e long.

No, non le ha neanche in Python:

In [1]: False + False
Out[1]: 0


Non mi sembra ci sia _nessun_ altro caso, in qualsiasi tipo numerico in
python, in cui si ha

b = a + a
type(b) != type(a)
a + a == b


Poi in matematica puoi dire che le ha, ma in un modo tale che, ristrette
ai booleani, siano assolutamente stupide (e non per questo sbagliate
formalmente). Ossia _non_ le considero operazioni sui booleani.

Ma se fa comodo farci giocare i booleani con gli int, ben venga...

> Deduco che
> float e int, che sono bestie diversissime, sono numeri e devono essere 
> trattati come numeri da quello che scrivi in seguito.
> 
> > In realtà ovviamente non è un problema di nomi. Il fatto è che non dirò
> > "guarda, miracolo dell'informatica, la mela è un numero", ma "guarda,
> > ...
> > tutte le volte che voglio.
> 
> Ricordo qualcosa in proposito su un libro di Schopenhauer...
> Tu hai parlato di mele, non io. Quello che vuoi fare con le mele è,
> essenzialmente, affar tuo.

Qual'è la differenza tra le mele e i bool? Che i bool sono "numeri"...
ma questa è una tua _ipotesi_.

(a scanso di equivoci linguistici: potrei anche voler chiamare i bool
"numeri" ma continuare a considerarli "diversi" dagli altri numeri, che
ritengo si assomiglino molto di più - che ne so, per esempio perché
capita di fare operazioni tra di essi anche al di fuori
dell'informatica, nel senso di "peso di una mela - float - per numero di
mele - int")


> > Stai cercando di motivarmi con dettagli (non nel senso di "trascurabili
> > per l'implementatore", ma nel senso di "auspicabilmente trascurabili per
> > l'utilizzatore") la "comodità" e la "sensatezza" (e addirittura la
> > necessarietà) di alcune regole degli operatori? In tutta onestà, non è
> > quello di cui stavamo parlando.
> 
> No: tu hai tirato in ballo un grosso paragone con la matematica, io ti stavo
> spiegando che spesso questo punto di vista è purtroppo fuorviante.
> Non puoi aspettarti che una cosa funzioni in un certo modo in Python
> perchè è così in matematica.


Mi aspetto che quando è possibile il Python faccia proprio in modo che
io possa illudermi. Ed è così molto spesso, e non a caso.



> >> BTW, non tirare in ballo xor e compagnia, al momento non hanno nulla a che vedere.
> > Nulla a che vedere con i booleani? 
> 
> Nulla a che vedere con il discorso, suvvia. Che trucchetto misero. :)
> Non e' per essere polemico, ma mi sembrava chiaro che stavamo parlando
> delle operazioni tipiche dell'aritmetica intera applicate ad interi e booleani
> in modo mischiato.


OK, ammetto che come quoting può essere stato equivoco, ma non è un
"trucchetto misero"... io ho tirato in ballo xor e compagnia per fare
_notare_ che le operazioni classiche dei bool sono diverse da quelle
degli altri numeri. Se lo xor è OT, lo sono anche i booleani :-)

Comunque sì, è un rivolo di conversazione abbastanza sterile.


> > Appunto, ma se ogni volta che due oggetti *si comportano come* nel senso
> > del duck typing avessi che risultano ==, impazzirei.
> 
> Purtroppo qui il problema e' molto "ideologico". Quando due oggetti "distinti"
> sono legittimati ad avere un == che dice che sono uguali? Boh, dipende
> dal dominio.

Sì, appunto.

> 
> >> Oltretutto, quello che probabilmente ti sfugge è che se un animale è un cane,
> >> un cane non è un intero.
> > 
> > Questo mi sfugge, sì. Forse manca la conclusione "ogni intero è
> > mortale"?
> 
> Oh, pardon. Era se cane is-a animale, tipicamente non animale is-a cane.
> 
> >> Ergo se un booleano è un intero, un interno non è
> >> un booleano.
> > Ah, beh, che sia così nell'implementazione attuale non c'è dubbio,
> > grazie.
> 
> No, accidenti. Tu continui a fare confusione su cosa sia l'ereditarietà.
> E ripeto, non e' polemica. 


Mi spiego meglio: ovviamente non stavo dicendo che, data A sottoclasse
di B, mi aspetterei

is_instance(B(), A) --> True

, ma che se A non introduce _niente_ di nuovo rispetto a B (e mi sembra
questo il caso per i booleani nei confronti degli int - a parte la
rappresentazione diversa, ovviamente), tanto vale abolirla...

... a meno che non siamo tanto affezionati alla rappresentazione proprio
perché per noi False e True _non_ sono 0 e 1.

> 
> >> 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. 
> > 
> > Di nuovo, trovo il duck typing fantastico.
> 
> Ti rendi conto che ti ho parlato di Ruby, che ha il comportamento da te richiesto,
> e tu mi hai parlato del duck typing? Non è che nel mezzo ci siamo persi qualcosa?
> 

No, ti dicevo solo che per me in questo caso Ruby è OT perché sul fatto
che
if [] : print "ciao"   ->   ...

è una bella cosa sono perfettamente d'accordo con te (e se ho capito
bene - ma ci avrò scritto 10 righe in vita mia - in Ruby non è così).

Pietro



Maggiori informazioni sulla lista Python