PDA

View Full Version : [Java] Neal Gafter - Language Parity: Closures and the JVM


shinya
15-02-2009, 11:44
Un talk molto interessante di mezz'oretta con Neal Gafter sul possibile futuro della JVM.

http://www.infoq.com/presentations/gafter-jvm-closures

shinya
16-02-2009, 13:25
up

... perchè è un talk interessante :)

cdimauro
16-02-2009, 13:28
Immagino. Vorrei avere il tempo per godermelo, ma finora non l'ho trovato.

Non si trova per caso una versione testuale e/o una sintesi?

banryu79
16-02-2009, 14:27
Immagino. Vorrei avere il tempo per godermelo, ma finora non l'ho trovato.

Non si trova per caso una versione testuale e/o una sintesi?

Quoto, shinya hai altre fonti più fruibili? Purtroppo oggi sono un po' incasinato col lavoro, domani è probabile ci dia un'occhiata, grazie per la segnalazione :)

shinya
16-02-2009, 15:07
Ho cercato un pochino, ma non ho trovato una trascrizione del talk. Ma dura davvero solo mezz'oretta (comprese le domande alla fine), quindi si fa prima a guardarlo direttamente secondo me :)

banryu79
16-02-2009, 15:59
Ho cercato un pochino, ma non ho trovato una trascrizione del talk. Ma dura davvero solo mezz'oretta (comprese le domande alla fine), quindi si fa prima a guardarlo direttamente secondo me :)
Benone, lo tengo buono per la pausa pranzo di domani ;)

Mixmar
16-02-2009, 17:06
Grazie del talk shinya, mooolto interessante.

PGI-Bis
16-02-2009, 17:51
Non è meno interessante quanto disse tempo addietro il buon Joshua Block

http://www.parleys.com/display/PARLEYS/The+Closures+Controversy?showComments=true

banryu79
17-02-2009, 13:31
Bene, ho ascoltato con interesse il talk, e mi piacerebbe sentire la vostra opinione.
Io ho poco da dire: un po' per il fatto che non sono un programmatore al 100% (nel mio lavoro la programmazione è solo una parte delle mie mansioni) e quindi ho anche poca esperienza in merito ma per quanto mi rigurada, personalmente, non riesco a vedere questa evoluzione nel linguaggio come rivoluzionaria; per lo stesso motivo non riesco a vederela ne come particolarmente positiva ne come particolarmente negativa.

Mi spiego, dopo aver visto del codice di chi programma con linguaggi funzionali e dopo aver dato occhiate a librerie tipo FunctionalJava ho avuto due reazioni:
-> di sconcerto, per la forma inizialmente "aliena" di certe sintassi non ortodosse per il programmatore Java, che sembrano (a prima vista) non avere niente a che spartire con lo stile del linguaggio (e quindi con la chiarezza immediata, con la facile e veloce lettura del codice);
-> di invidia, nel constatare che la forma "aliena" riusciva a sintetizzare molto bene (e, dopotutto a ben guardare, con eleganza) codice che nell'equivalente Java sarebbe stato al confronto molto più prolisso e verboso (a volte questo rende le cose più chiare, altre invece, specie se è troppo prolisso le rende comunque la lettura più ardua a causa della memoria a breve termine del lettore).

In sostanza queste sono state le mie reazioni; a onor del vero non mi sono preoccupato troppo dell'impatto che potrebbero avere sulla JVM queste "aggiunte" al linguaggio.

Dico "aggiunte" perchè di fatto mi pare che siano un qualcosa "in più" che non era previsto fin dalla nascita e la cui giustificazione all'introduzione è appunto che Java è uno dei pochissimi linguaggi mainstream a essere senza clojure e quindi dotiamolo di questa funzionalità, anche in vista di usare Java come "lingua franca" per poter far interoperare codice "straniero" (Ruby, Python, Scheme, eccetera...) con la JVM.

Vabbuò, così di primo acchitto io penso: se male non fa, va bene, finchè le funzionalità/costrutti nuovi introdotti non divengono "obbligatori" e/o non sono troppo "pervasivi" a me che fastidio mi danno?

Se poi apportano dei vantaggi, ben vengano.

shinya
18-02-2009, 09:07
Sostanzialmente credo sia una questione di porsi degli obiettivi.
Io ne vedo due, e li ritengo entrambi validi, basta scegliere.

Se si vuole che java diventi un 'workhorse' stabile, semplice, con il quale tutti i linguaggi su JVM possano interfacciarsi senza problemi, comprensibile da tutti i programmatori pigri che non hanno voglia di studiare niente di più di quello che sanno, e di farlo diventare, di fatto, il nuovo cobol, va bene, non aggiungiamo una virgola al linguaggio. Ma a questo punto bisognerebbe chiedersi se l'aggiunta, che ne so, dei generics sia stata una buona scelta (io non credo, soprattutto perchè sono solo a compile-time).

Se invece si vuole che java diventi un'alternativa moderna a linguaggi molto più avanti (tipo c#, che storicamente ne è la controparte... storicamente ho detto, non che lo sia) allora perchè fermarsi ai generics?? Mettiamo anche tutte le altre cose che sono in giro dagli anni 70 (e forse prima), ad esempio le closure. Tanto più che i generics sono un'aggiunta di gran lunga più complicata delle closure, anche se sembrano semplici a livello superficiale.

Il mio punto di vista è che la strada da seguire avrebbe dovuto essere la prima, ma che per ragioni storiche l'unica strada percorribile sia la seconda. Cosi com'è adesso è un lavoro a metà.

Per quanto riguarda il discorso functional-java. A me piace, la utilizzo quando posso, ma è un totale abuso del linguaggio, lo riconosco. E' il tipico "The prisoner falls in love with his chains" :)

PGI-Bis
18-02-2009, 09:48
Ecco, avevo scritto un posto kilometrico pieno di cose intelligenti e m'è partito internet explorer. Dico due stupidaggini in sintesi.

Funzioni bene, sintassi { T => T } orrenda.

Tanto dopo i generici potremmo buttarci dentro anche una bomba atomica e sembrerebbe robetta.

C'è un altro talk, un po' lunghetto, sul futuro dei linguaggi di programmazione che dice un sacco di cose interessanti.

http://blog.jaoo.dk/2008/10/07/the-future-of-programming-languages/

banryu79
18-02-2009, 11:10
Ecco, avevo scritto un posto kilometrico pieno di cose intelligenti e m'è partito internet explorer. Dico due stupidaggini in sintesi.

Se puoi e vuoi ti invito a ripostare le tue osservazioni perchè mi interesserebbe ascoltarle (leggerle).

Mi interesserebbe sentire anche le opinioni di altri, sia Java user che user dei linguaggi che potrebbero interoperare con la JVM...

banryu79
19-02-2009, 14:07
Non è meno interessante quanto disse tempo addietro il buon Joshua Block

http://www.parleys.com/display/PARLEYS/The+Closures+Controversy?showComments=true
Visionato...
Orrore e disgusto per via dei problemi legati all'aspetto del non-local return nelle closure e delle variabili locali (ma "esterne alla closure") tenute in "animazione sospesa" dalle stesse e quindi potenzialmente modificabili da thread esterni :cry:

Comunque vista la datazione del talk che era relativo a BGGA spero che se proprio devono introdurre le closure in "modo violento" nel linguaggio il risultato non sia l'alienazione totale (almeno per me) che mi è sembrata da questo talk.

Spero invece in un approccio diverso, la soluzione syntatic sugar mi sembra meno stravolgente e comunque efficace, perchè sul discorso relativo alla possibilità di nuove strutture di controllo definite dalla libreria la mia opinione è che non ne sento tutto questo bisogno... almeno non tanto da pagarne il prezzo in quel modo.

Alla fine la considerazione di Joshua Block di usare Scala (il bytecode prodotto è JVM compatibile) come alternativa a Java qualora fosse necessario un approccio funzionale mi pare sensata.

Molto interessante invece l'introduzione di nuovi appositi costrutti specificamente indirizzati a semplificare/snellire singoli aspetti: come per esempio un apposito blocco ARM che chiude automaticamente le risorse allocate, da usarsi per snellire il codice dai try-catch-finally usuali ed evitare relativi errori, o come la sintassi più snella nell'implementare una interfaccia mediante classe definita e istanziata "on the fly" nel codice.

thebol
19-02-2009, 16:29
http://tech.puredanger.com/2009/02/16/java7-update/

sembra che le closure non ci saranno in java7

bestemmie a piacere.

Sto provando ultimamente a creare interfacce e innerclass per simularle, ma pur funzionando è tedioso.


Una nota positiva è invece quella delle istruzioni a livello di bytecode per facilitare la scritture di linguaggi dinamici su JVM. (ne trarranno beneficio sicuramente JRuby e Groovy, probabilmente anche scala e clojure).

banryu79
19-02-2009, 17:15
http://tech.puredanger.com/2009/02/16/java7-update/

Letto.


sembra che le closure non ci saranno in java7

bestemmie a piacere.

Perchè?
Le closure sono così indispensabili?

Lo chiedo a causa della mia ignoranza.
Teoricamente so cos'è una closure, in senso stretto, ma, diciamo operativamente, no (anche se ho pasato del tempo a giochicchiare con SmallTalk).

Mi spiego: essendo abituato a programmare in Java e non in un linguaggio funzionale, ed essendo abituato a programmare solo in un ristretto contesto, non ho mai sentito la stringente mancanza delle closure.

Quello che vorrei capire, è in quali contesti, casi d'uso o situazioni risulta migliore come strumento, e di quanto.

Non lo chiedo come provocazione, ma come sincera richiesta di illuminazione perchè sono ignorante sull'argomento e vorrei capire quale reale utilità potrebbero apportare anche al mio lavoro.

marco.r
19-02-2009, 22:54
Le closure sono così indispensabili?

Indispensabili no, soprattutto in un linguaggio ad oggetti, possono risultare pero' molto comode. In teoria non ne hai bisogno perche' tutto quello che puoi fare con le closure lo puoi fare con oggetti funzione o simili. Solo che sono molto piu' "leggere".

C'e' da dire prima di tutto pero' che nella proposta mostrata piu' sopra da PGI-Bis, hanno scelto un modo decisamente contorto per introdurla (aggiungo che l'autore ha calcato un po' la mano scegliendo esempi ad arte), che ne riduce parecchio l'utilita'. Riporto l'esempio riportato in una slide:

static Pair<{ => int },{ => int }> joinedCounters( int initial )
{
return Pair.<{ => int },{ => int }>of( { => initial++ }, { => initial++ });
}

Vedrei piu' piacevole poter scrivere qualcosa del tipo

static Pair< int (), int () > joinedCounters( int initial )
{
int f(){ return initial++; }
return Pair< int (), int () >( f, f );
}

Che a me risulta un po' piu' chiaro (forse per l'abitudine ad altri linguaggi) anche se probabilmente non sarebbe inseribile cosi' come e' come estensione.

Detto questo, molto spesso l'uso di closure e' piu' conciso che non l'uso di oggetti, e soprattutto migliora la localita'. Ad esempio se devi passare un oggetto, lo devi definire fuori dal corpo della funzione, per cui invece che avere il codice relativo sotto mano devi andare a guaradre cosa fa. Oltre al fatto che in casi molto semplici (come quello sopra di un incrementatore) scrivi 5-6 linee di codice invece che una sola.

Un uso molto importante e' quello della gestione delle risorse. Vista la presenza del garbage collection, in Java in generale non sappiamo quando viene deallocato un oggetto e se a questo oggetto e' associato una risorsa "esterna" (collegamento a db, file, etc.) dobbiamo liberare la risorsa associata a mano oppure rischiare di esaurirle. Se pero' posso passare un pezzo di codice, allora posso scrivere una funzione/metodo che prende ad esempio il nome del file e il codice da eseguire, apre il file, esegue il pezzo di codice, e si preoccupa della pulizia non appena il codice e' stato eseguito.

Qualcosa del tipo (attenzione, e' pseudo-codice !)

void withFile( String filename, {File => } snippet )
{
File f = ... ;
try
{
snippet(f);
}
/* ... gestione eccezioni */
finally
{
f.close();
}
}



Che potrei usare piu' o meno cosi'.

withOpenFile( "pippo.txt", { file =>
file.writeLine("blabla");
});


Ora, come dicevo sopra la sintassi e' abbastanza orrenda, ma spero di aver reso l'idea (tenendo presente che scrivo codice Java di rado, e penso si noti :D)

banryu79
20-02-2009, 08:35
@marco.r
Grazie delle spiegazioni, alcuni punti che hai messo in luce mi stanno aiutando a comprendere, anche se non ho ancora capito se un bravo programmatore ad oggetti, uno che ha appreso best practices e design patterns e li sa applicare quando, dove e come serve, ne abbia realmente bisogno (per esempio rispetto al fatto che con le closure hai la possibilità di migliorare la località)


Un uso molto importante e' quello della gestione delle risorse. Vista la presenza del garbage collection, in Java in generale non sappiamo quando viene deallocato un oggetto e se a questo oggetto e' associato una risorsa "esterna" (collegamento a db, file, etc.) dobbiamo liberare la risorsa associata a mano oppure rischiare di esaurirle. Se pero' posso passare un pezzo di codice, allora posso scrivere una funzione/metodo che prende ad esempio il nome del file e il codice da eseguire, apre il file, esegue il pezzo di codice, e si preoccupa della pulizia non appena il codice e' stato eseguito.

Sì perfetto, ma nel talk di J. Block ci si indirizza alla soluzione dello stesso problema in un altro modo: intoduci un nuovo costrutto da usarsi al posto del tradizionale try{}cacth(Exception e){}finally{} quando hai a che fare con le risorse, per sempio con un semplice try{} che implicitamente chiude correttamente la risorsa quando si esce dal suo scope.

Molto semplice, e conciso, direi.

thebol
20-02-2009, 09:32
Letto.


Perchè?
Le closure sono così indispensabili?

Lo chiedo a causa della mia ignoranza.
Teoricamente so cos'è una closure, in senso stretto, ma, diciamo operativamente, no (anche se ho pasato del tempo a giochicchiare con SmallTalk).

Mi spiego: essendo abituato a programmare in Java e non in un linguaggio funzionale, ed essendo abituato a programmare solo in un ristretto contesto, non ho mai sentito la stringente mancanza delle closure.

Quello che vorrei capire, è in quali contesti, casi d'uso o situazioni risulta migliore come strumento, e di quanto.

Non lo chiedo come provocazione, ma come sincera richiesta di illuminazione perchè sono ignorante sull'argomento e vorrei capire quale reale utilità potrebbero apportare anche al mio lavoro.

non sono tanto le chiusure in senso stretto, ma la possibilità di creare funzioni da passare a un altra funzione, senza creare una classe ogni volta.

Sono comode, ci si può vivere senza e il costrutto java per fare quel lavoro sono le inner class o anonymous inner class.

Perchè sono comode? Facilitano l'estensibilità delle classi. L'esempio classico è fare un azione per ogni elemento di una collection. I vari metodi che trovi in ruby, groovy etc tipo collect, join, map, etc. Si fanno anche in java, ma hanno bisogno di più lavoro dietro.

Oppure hai una classe a cui passi dei parametri. Potresti aver bisogno di comportamenti custom non coperti dai parametri previsti. Se si riuscisse a passare una funzione per personalizzare quel comportamento rende il sistema più estendibile. Per fare questo in java devi passare una classe sempre. Avendo le funzioni come first class object, è più semplice gestire queste situazioni.

thebol
20-02-2009, 09:36
static Pair<{ => int },{ => int }> joinedCounters( int initial )
{
return Pair.<{ => int },{ => int }>of( { => initial++ }, { => initial++ });
}

in effetti la sintassi è brutta

banryu79
20-02-2009, 12:50
Oppure hai una classe a cui passi dei parametri. Potresti aver bisogno di comportamenti custom non coperti dai parametri previsti. Se si riuscisse a passare una funzione per personalizzare quel comportamento rende il sistema più estendibile. Per fare questo in java devi passare una classe sempre. Avendo le funzioni come first class object, è più semplice gestire queste situazioni.
Ok, ho capito, sei steto chiarissimo, grazie della spiegazione.

cdimauro
20-02-2009, 13:09
in effetti la sintassi è brutta
Brutta vuol dire fargli un complimento. :asd:

banryu79
20-02-2009, 13:26
Brutta vuol dire fargli un complimento. :asd:
Concordo, a me fa :Puke:

marco.r
21-02-2009, 15:59
Sì perfetto, ma nel talk di J. Block ci si indirizza alla soluzione dello stesso problema in un altro modo: intoduci un nuovo costrutto da usarsi al posto del tradizionale try{}cacth(Exception e){}finally{} quando hai a che fare con le risorse, per sempio con un semplice try{} che implicitamente chiude correttamente la risorsa quando si esce dal suo scope.

Molto semplice, e conciso, direi.

Non mi piace. In sostanza propone sintassi specifiche per diversi problemi che potrebbero essere risolti allo stesso modo.
Di per se' possono essere carine, pero' diventano N costrutti che interagiscono tra di loro rendendo piu' complesso il linguaggio e complicate le interazione.
Ovviamente anche le closure bisogna implementarle bene. Ad esempio questo succede in Ruby.
Gestione automatica delle risorse ? closures

File.open("filename.txt") do |file|
# bla bla
end

Vuoi fare la stessa cosa su un mutex ? Ti basta implementare un classe col metodo opportuno

Mutex m;
m.lock do
# bla
end

Iterazione su un qualche tipo di struttura dati?

arr = [1,2,3]
arr.each do |x|
puts x + 3
end


Sempre la stessa sintassi. La trovo migliore che avere una sintassi per le classi anonime, una per iterare, una per la gestione delle risorse...