Paul Graham v článku Revenge of the Nerds (dostupný i český překlad) píše, že kdybyste se Dilbertova šéfa zeptali, v čem naprogramovat software, tak vám odpoví: Java. Ale jazyky se svými schopnostmi liší. Ukazuje to sice na akademické a nepraktické úloze, která ovšem o jazycích leccos vypovídá. Úlohu jsem si připomněl v souvislosti 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-class object (nebo taky citizen), což ve stručnosti znamená, že nešlo předat metodu jako parametr jiné metodě. Pokud vám tahle vlastnost nechyběla, tak možná proto, že jste si to nikdy nezkusili.

Po všech těch odkladech 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 kalkulem, což není plnohodnotné 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é referencované z lambda výrazu definované jako final nebo alespoň efektivně final, což mě nepříjemně překvapilo, neboť jsem čekal, že s verzi 8 už dokážu napsat podobně elegantní řešení jako v Groovy. Mimochodem koncept closure byl implementován v jazyce Scheme již v roce 1975.

Řešení

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