W Perl istnieją trzy główne typy deklaracji zmiennych: my, our i state.
sub example_state { state $counter = 0; $counter++; return $counter; } for (1..3) { print example_state(), " "; # Wyświetli 1, następnie 2, następnie 3 }
Gdzie używać:
my — prawie zawsze preferowany wybór dla zmiennych, jeśli nie ma powodu, aby mieć dostęp globalny.our — do eksportowania zmiennych między modułami, gdy wymagane jest współdzielenie.state — jeśli zmienna ma "zapamiętywać" wartość między wywołaniami funkcji (na przykład licznik wywołań).Czy zmienna zadeklarowana za pomocą our może być zamknięta (captured) w zamknięciu na równi z my?
Zwykle odpowiada się "tak, to wygodne", ale to nieprawda. Zmienna our jest globalna dla pakietu, a zamknięcie w zasadzie nie wiąże jej wartości w momencie tworzenia closure, lecz odwołuje się do niej przez globalną nazwę. Dlatego jej "wartość" może zmienić się na zewnątrz closure i dotknie wszystkich zamknięć!
our $x = 10; my $closure = sub { return $x; }; $x = 42; print $closure->(); # Zwróci 42, a nie 10
Historia
W dużym skrypcie do parsowania logów zmienne były deklarowane jako our dla "wygodnego dostępu" z różnych funkcji modułu. W rezultacie zmiana tych zmiennych w jednej funkcji prowadziła do nieoczekiwanego zachowania w innej, psując równoległe przetwarzanie logów.
Historia
Użycie my dla zmiennych, których wartość miała być zachowywana między wywołaniami funkcji (na przykład, licznik w rekursywnym przechodzeniu), prowadziło do zresetowania wartości przy każdym wywołaniu, co powodowało nieprawidłową logikę przechodzenia. Zmiana na state rozwiązała problem.
Historia
Niepoprawne użycie our w importowanym module (eksport zmiennych nie przez Exporter) spowodowało kolizję nazw przy dołączeniu dwóch różnych modułów, które używały tej samej nazwy zmiennej. W rezultacie dane "skakały" z jednego kontekstu do drugiego.