Perl jest językiem o wyraźnej zależności od kontekstu: wynik wyrażenia zależy od tego, w jaki sposób jest używany. Historycznie uczyniło to język niezwykle elastycznym, jednak nawet doświadczeni programiści mogą popełniać błędy, nie uwzględniając szczególnych cech działania kontekstu skalarnych i listowych.
Pytanie to pojawiło się z pierwszymi wersjami Perla, kiedy to zakładano, że ta sama operacja może zwracać tablicę lub pojedynczą wartość — na przykład wywołanie funkcji localtime może zwracać albo listę, albo łańcuch w zależności od sytuacji.
Problem polega na tym, że niewłaściwe przetwarzanie kontekstu prowadzi do nieoczekiwanych błędów: na przykład zbędne elementy, puste wyniki lub dziwne zachowanie wyrażeń logicznych.
Rozwiązanie — zawsze wyraźnie zrozumieć, w jakim kontekście wywoływana jest funkcja lub wyrażenie, używać wbudowanej funkcji wantarray w swoich podprogramach i nie dopuszczać do niejawnego mieszania kontekstów.
Przykład kodu:
sub may_return { return wantarray ? (1, 2, 3) : "wynik skalarowy"; } my @arr = may_return(); # zwróci (1,2,3) my $val = may_return(); # zwróci "wynik skalarowy"
Kluczowe cechy:
Czy można określić, czy wyrażenie jest używane w kontekście void, wewnątrz samej funkcji?
Odpowiedź: Nie, tylko skalarny lub listowy. W Perl 5 nie ma funkcji określającej kontekst void wewnątrz podprogramu — funkcja wantarray zwraca undef w tym przypadku, ale dla innego zachowania.
Przykład kodu:
sub example { return wantarray ? (1,2) : wantarray ? undef : "skalar"; # niepoprawne }
Czy funkcja może zwracać różne typy danych w zależności od kontekstu?
Odpowiedź: Tak, jest to całkowicie dopuszczalne i często stosowane.
Czy zachowanie operatorów (na przykład shift, pop) zależy od kontekstu?
Odpowiedź: Tak. Na przykład, gdy shift jest wywoływane wewnątrz funkcji — zależy, czy @_ (globalnie czy leksykalnie) jest używane, a wynik czy będzie przekazywany jako skalar czy jako lista.
Programista napisał funkcję, która zawsze zwraca listę, nie uwzględniając kontekstu skalarnego. Jeśli tę funkcję wywoła się w kontekście skalarnym, otrzymamy tylko ostatni element listy.
Zalety:
Wady:
W funkcji używa się wantarray i zwraca się albo listę, albo sensowny skalar lub undef.
Zalety:
Wady: