Niedawno z ciekawości zajrzałem na stronę PHP.net w poszukiwaniu pomysłu na wpis. I znalazłem go bardzo szybko. Na początku sierpnia wydano pierwszą wersję alfa PHP 5.3. Postanowiłem przyjrzeć się z bliska liście zmian. Moją uwagę przyciągnęła dosyć dziwnie brzmiąca zmiana: "Lambda functions and closures". Po bliższym przyjrzeniu się zmianom opisanym na wiki PHP, stwierdzam że takiej funkcjonalności niesamowicie mi brakowało! Pewnie spora część użytkowników tego bloga potrafi programować w JS. Jeżeli nie, to spójrzcie na ten kawałek kodu:
something = function() { return true; }
something();
W przypadku JavaScript'u, każdą funkcję można było przypisać zwyczajnie do zmiennej, a następnie wykonać ją lub przekazać do innej funkcji jako parametr. Zobaczmy jak to wygląda w przypadku JS:
something = function() { return true; }
anyThing(something, 'string');
W jaki sposób uzyskać podobną funkcjonalność w PHP? Nie jest to takie łatwe. Musimy wykorzystać do tego instniejącą funkcję create_function lub zdefiniować ją wewnątrz skryptu.
//wersja z create_function()
$fn = create_function('$param1', 'echo $param1; return true;');
$fn('something');
//wersja z definiowaniem własnej funkcji
if(!function_exists('lambda_1'))
{
function lambda_1($param1)
{
echo $param1; return true;
}
$fn = 'lambda_1';
}
$fn('something');
A tutaj już wersja z tak zwaną funkcją lambda (nie mam pojęcia jak to przetłumaczyć):
$fn = function($param1)
{
echo $param1;
return true;
};
$fn('something');
Warto zwrócić uwagę na średnik znajdujący się po zamykającej klamrze. Według wiki PHP, jest on niezbędny z niewiadomych mi powodów (coś z parserem), poza tym twórcy tego rozwiązania twierdzą, że podobna składnia i tak funkcjonuje już w pętli while-do.
Jakie są zalety takiego rozwiązania? Jest ich kilka. Po pierwsze, działa nam kolorowanie składni (w przypadku create_function treść funkcji znajduje się w ciągu znaków - tracimy sporo na czytelności). Po drugie, nie musimy obawiać się, że funkcja o danej nazwie może już istnieć. Nie musimy także troszczyć się o przypisanie nazwy funkcji do zmiennej, wszystko dzieje się automatycznie. Dodatkowo, według wiki PHP, rozwiązanie przy pomocy create_function() nie jest cache'owane przez różnej maści optymalizatory kodu (vide Zend Optimizer). Przejdźmy teraz do drugiej funkcjonalności. Są to tzw. closures. Pozwalają one na przekazanie do funkcji lambda na stałe pewnych zmiennych. Działanie bardzo proste do global'i, jednak w tym przypadku do funkcji przekazywana jest kopia obiektu (chyba, że dodamy przed nazwą zmiennej ampersand). Składnia jest bardzo prosta:
$var = function($param1, $param2) use($globalvar)
{
return $param1 + $param2 + $globalvar;
}
W ten sposób nasze lambda functions mogą zawierać pewne dynamiczne dane, które będą pochodziły z zewnątrz skryptu, bez konieczności ich późniejszego przekazywania jako parametr. Muszę przyznać, że obydwie funkcjonalności naprawdę mocno mnie zainteresowały i nie mogę się doczekać paczek dla Arch'a z wersjami testowymi PHP żeby pobawić się nowym PHP5.3. W następnych wpisach pojawią się dalsze funkcjonalności PHP5.3 które zostały już wprowadzone. Na które z nich czekacie najbardziej? A może nie podoba wam się kierunek, w którym zmierza PHP?