Såvida man inte helt ignorerat vad som händer på Java-fronten de seanste två åren så kan man inte ha missat att det förekommer en rätt så hetsig debatt kring något som kallas Closures. Senast så skrev James Gosling ett inlägg på sin blog som genererade kommentarer i en vecka efteråt. Debatten kring detta handlar om huruvida closures ska inkluderas i Java och hur det då ska lösas. Tyvär så är vetskapen om vad en closure är för något ganska begränsad, åtminstone inom Java-världen. Detta beror dels på att begreppet inte riktigt antyder vad det handlar om samt att det inte varit tillgängligt i de main-stream programspråk som vi haft de senaste 20 åren (t.ex. C/C++, Delphi, Java, C# osv.). Nu är dock closures något som är ganska viktigt, både i hur det löses och att utvecklare förstår vad det handlar om, så låt mig göra ett försök att göra bilden lite klarare.

Namnet closures härstammar från programspråket Scheme, som är en Lisp-variant som två killar vid namn Guy Steele och Gerald Jay Sussman skapade i mitten på 70-talet. Problemet med andra Lisp-dialekter var att de var ganska stökiga och komplicerade, så man gjorde en stor uppstädning och resultatet blev ett språk som blev lexically scoped (Hittade ingen bra svensk översättning. Förslag mottages gärna.), till skillnad från tidigare varianter som var dynamically scoped. Om du nu inte har en susning om vad det betyder så innebär det att du är normal och tillhör den stora massan av kodare som haft förmånen att inte behöva bry sig om sådana skumma saker. Jag tänker inte gå in på vad dynamically scoped betyder utan hoppar direkt på att försöka förklara lexically scoped.

I Java har vi scope som innebär att en variabel, metod eller klass har en begränsad ”synlighet”. Det här gör, till exempel, att du kan deklarera en variabel med samma namn både som medlemsvariabel och lokal variabel i en metod. Detta betyder att vår kod har ett visst scope, eller omfång för att använda ett svenskt ord. Det går inte att deklarera två variabler, eller metoder, med samma namn (och parameter-lista om det är en metod) i samma scope. Inga konstigheter här inte, detta är något vi alla kan som ett rinnande vatten. Låt oss gå tillbaka till Scheme och closures.

Scheme införde en möjlighet att deklarera ett lambda uttryck som behåller en referens till alla variabel i det scope som den deklarerades i. Hängde ni med? Ett lambda uttryck är i princip detsamma som en funktion (alltså en metod som inte är kopplad till en viss klass, för er som inte kodat ett funktionellt eller procedurellt språk tidigare). Funktionen kan sen skickas som parameter till andra funktioner (eller i Javas fall, metoder) och kommer behålla alla referenser till de lokala variabler som fanns i det scope som den deklarerades i. De variabler som du sedan använder i funktionen och som är deklarerade i samma scope som funktionen kallas free variables. När sen hela uttrycket, d.v.s. funktionen och dess free variables, evalueras (inte samma sak som att anropa funktionen alltså) så har du en closure.

I Scheme, som är ett rent funktionellt språk (och fantastiskt roligt att koda i, förutsatt att man tycker det är ok att bli konstig i bollen efter några dagar), har ett lexical scope som bara berör variabler. I Java, som är ett mycket mer komplext programspråk, blir det lite mer att tänka på. Först och främst så har Java lite fler saker att hantera i sina scope än vanliga variabler. Du har metoder, typer, checked exception och uttryck såsom break, continue, this och return. Vad skulle det t.ex. innebära om du skrev ”break” i din closures-funktion? Eller ”return”? Tanken är att dessa uttryck ska exekveras i det scope som din closure omslöt. Så om du skapar en closure där du har en return i din funktion så kommer det innebär att du gör en return i den metod som du deklarerade din closure i, och inte return för funktionen. Knepigt? Jo, och det är därför som det är en sån debatt kring det hela. Nu undrar du säkert vad man ska ha det hela till. Om vi klarat oss såhär länge utan closures så kan det väl inte vara så viktigt att få med det nu.

Tyvär är det så att många problem som vi ofta spring på i Java idag blir mycket enklare att lösa med closures. Exempel: alla har vi någon gång kodat ett Swing GUI. När vi ska lägga på en funktion på en knapp så anropar vi något i stil med följande:

addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent event) {
// gör nånting...
}
});

Vi skapar alltså en anonym inre klass bara för att lägga lite funktioner på en knapp. När man gjort detta för ett helt GUI så börjar man må smått illa av alla anonyma inre klasser som kladdar ner ens annars så fina kod. Ett annat problem är att om du vill nå en lokal variabel i din actionPerformed-metod så måste den vara final, vilket kanske inte alltid är så lämpligt. Med en closure så blir det dels mindre kod och samtidigt så slipper du deklarera dina variabler med final.

Ovanstående är bara ett av många exempel där closures gör koden mer läsbar (vilket i sin tur innebär färre buggar och enklare att underhålla) och ger oss ett verktyg som kan ersätta många andra tilläggsförslag som gjorts för Java på sistone. Införandet av closures i Java skulle alltså lyfta språket i sin helhet och minska behovet att bygga in ytterligare komplicerade konstruktioner. Det är alltså inte så att closures ger dig en möjlighet att göra saker du inte kunde göra tidigare. Java är ju ett Turing-komplett språk, så allt går faktiskt att uttrycka redan idag. Problemet är alltså att många återkommande uttryck är på tok för komplexa och större än vad de borde vara.

Så hur der det ut med Closures i Java då? Som det verkar just nu så kommer vi se att det kommer med i Java 7. Neal Gafter är en av de som jobbar mest med detta och skriver rätt mycket om det på sin blogg (när han inte skriver om Java Puzzlers och annat skoj) . Bob Lee (som också jobbar på Google) har presenterat en alternativ, light-variant, av closures för Java (syntaktisk socker ovanpå anonyma inre klasser i princip). Sen finns det en hel webb-plats som är dedikerad enbart för Java Closures och hur det kan lösas. Det finns en hel del att läsa om det hela och du kan även tanka hem olika implementationer av det hela för att testa.

Det är starkt rekommenderat att man sätter sig in i och lär sig förstå vad closures är för något, eftersom det garanterat kommer komma med i nästa version av Java och detta är en ändring av språket som är mycket större än vad auto-boxing, generics och annotations var när Java 5 kom. Jag kan rekommendera två presentationer som gjordes förra året och som finns upplagda på Parleys.com. Den ena var vad som genererade Goslings sensate blogginlägg i ämnet och den andra är Neal Gafters uppdatering vad som hänt på closures-fronten rent tekniskt.