This post comes from the first version of this blog.
Please send me an email if anything needs an update. Thanks!

Zaczynając przygodę z programowaniem każdy z nas otrzymał od swoich mentorów kilka informacji, które należało przyjąć za podstawę i z jako takimi aksjomatami po prostu nie dyskutować. Z reguły na początku kariery nikogo nie zastanawiają ani nie denerwują takie ograniczenia, stąd trwamy w naszym przeświadczeniu, że to, co robimy jest zgodne z jak najlepszymi technikami programowania. W dzisiejszym wpisie chciałbym nieco nagiąć jedną z tych reguł i pokazać Wam pewną sztuczkę czasem istotnie ułatwiającą życie, szczególnie podczas tworzenia kodu w języku PHP.

Wstęp.

Jedną z takich “niedyskutowalnych” rzeczy była dla mnie przekazywana od początku informacja o tym, że wynik funkcji / metody to zawsze jedna wartość / zmienna. Nawet brak tej wartości można było uznać za wartość, ponieważ w Pascalu [który był pierwszym językiem programowania jaki poznałem] paradygmat proceduralny był realizowany za pomocą dwóch elementów - procedur [nie zwracających wartości, odpowiednik funkcji zwracających void w C / C++] i funkcji [które “coś” zwracały], także nawet było to podzielone na dwa oddzielne byty.

Informację tą przyjąłem jako w miarę logiczną, w końcu tradycyjne, “licealne” funkcje omawiane na lekcjach matematyki nie odbiegały specjalnie od tego modelu. Wraz z postępem technologicznym i towarzyszącym mu zwiększaniem możliwości języków programowania oraz narzędzi dla nich pojawiły się nowe, ciekawe sposoby na “obchodzenie” aksjomatów przyswojonych na etapie nauki podstaw.

Problem.

Jeśli odniesiemy się do problemu postawionego w tytule wpisu w sposób tradycyjny, szybko zauważymy, że teoretycznie nie jest możliwe wykonanie takiej funkcjonalności. Nie ma żadnej konstrukcji językowej, która pozwalałaby na zrobienie tego w sposób intuicyjny, a więc np. tak:
1
2
3
4
5
6
7
8
9
// !!! invalid code !!!
// !!! do not use in testing / production environment !!!

function returnTwo($first, $second)
    {
    return $first, $second;
    }

$first, $second = returnTwo(12, 34);

Wynika z tego jednoznacznie, że konieczne będzie użycie pewnej sztuczki, pozwalającej “oszukać” jednowartościowy system do podstawienia żądanych wartości pod wymagane identyfikatory zmiennych. Niniejszym informuję, że moment jej wyjawienia następuje… już. ;]

Rozwiązanie.

W języku PHP istnieje bardzo ciekawa konstrukcja, której na imię list. Dokumentacja tej "funkcji" znajduje się w manualu, stąd zainteresowanych dokładnym wyjaśnieniem zapraszam tutaj. Słowo "funkcja" wziąłem w cudzysłów, ponieważ teoretycznie jest ona umieszczona w kategorii "Array Functions", ale jej wykorzystanie w tym kontekście jest mocno dyskusyjne, a z tego co pamiętam, to nawet Eclipse inaczej koloruje wystąpienie tego słowa kluczowego. ;] Ja postaram się wyjaśnić jej działanie na przykładzie - to nie jest trudne, więc lektura manuala jest polecana tylko "dłubiącym" na poziomie podobnym do mojego - ja też muszę wiedzieć jak, co, gdzie, kiedy i za ile. ;]

Aby uczynić z pokazanego wyżej “niedziałającego” kodu kod poprawny, wymagane będą [na szczęście] niewielkie zmiany. Wykorzystamy tutaj bardzo ciekawą sztuczkę, polegającą na zwróceniu z naszej funkcji pojedynczej wartości - tablicy - a następnie podstawieniu jej elementów pod “listę” naszych zmiennych. Jak wyglądałby w tym przypadku nasz kod? Spójrzmy na listing:

1
2
3
4
5
6
function returnTwo($first, $second)
    {
    return array($first, $second);
    }

list($first, $second) = returnTwo(12, 34);

Wydaje mi się, że podany wyżej kod jest dość jasny, aczkolwiek i tak napiszę swój komentarz. ;] Zauważmy zmiany w obu fragmentach kodu - w funkcji pojawia się zamykający listę argumentów, dynamicznie budowany array(), a w wywołaniu i podstawieniu wartości, mamy zamkniętą listę zmiennych w funkcji list(). W ten sposób możemy w automatyczny sposób wykorzystać poszczególne elementy bez zbędnego kodu podstawiającego “ręcznie” odpowiednie elementy do odpowiednich zmiennych. Funkcjonalnie jest to równoważne poniższemu rozwiązaniu:

1
2
3
4
5
6
7
8
function returnTwo($first, $second)
    {
    return array($first, $second);
    }

$result = returnTwo(12, 34);
$first = $result[0];
$second = $result[1];

Co powinno być jasne bez dodatkowego komentarza z mojej strony. ;]

Podsumowanie.

PHP jest językiem który posiada bardzo wiele takich "pomysłów" na skrócenie kodu. Do nas należy decyzja, czy chcemy zrezygnować z czytelności i wykorzystać tego typu sztuczki, czy jednak wolimy kod maksymalnie "standardowy". Jeśli znacie inne tego typu sposoby - podzielcie się nimi w komentarzach. Z góry dziękuję!