Paul Graham v článku Revenge of the Nerds (dostupný i český překlad) píše, že kdybyste se Dilber­tova šéfa zeptali, v čem naprog­ra­movat software, tak vám odpoví: Java. Ale jazyky se svými schop­nostmi liší. Ukazuje to sice na akade­mické a neprak­tické úloze, která ovšem o jazycích leccos vypovídá. Úlohu jsem si připomněl v souvis­losti s uvedením Javy 8. Zajímalo mě, jak obstojí.

Akumulátor

Chceme napsat funkci, která generuje akumulátory: funkci která vezme číslo n a vrátí funkci, která bere jiné číslo i a vrací n zvýšené o i.

Java

V Javě nebyla metoda first-c­lass object (nebo taky citizen), což ve struč­nosti znamená, že nešlo předat metodu jako parametr jiné metodě. Pokud vám tahle vlast­nost nechyběla, tak možná proto, že jste si to nikdy nezkusili.

Po všech těch odkla­dech jsem sázel, že tunel Blanka bude hotová dřív než Java 8, ale naštěstí jsem se mýlil. Java 8 přichází, kromě jiného, s lambda kalku­lem, což není plnohod­notné closure.

Closure mají přístup k proměnným mimo vlastní definici (proto se jim také říká uzávěry, anglicky closures, uzavírají totiž lexikální kontext funkce nebo metody, v níž jsou definovány).

(Lambda výrazy, uzávěry, bloky)

V Javě bohužel musí být lokální proměnné referen­co­vané z lambda výrazu defino­vané jako final nebo alespoň efektivně final, což mě nepříjemně překva­pilo, neboť jsem čekal, že s verzi 8 už dokážu napsat podobně elegantní řešení jako v Groovy. Mimochodem koncept closure byl imple­men­tován v jazyce Scheme již v roce 1975.

Řešení

Níže nalez­nete řešení v Groovy, Javě 7 a Javě 8, ke kterému mi pomohly odpovědi na mou otázku na stackoverflow.com