Historia pytania:
Wycinki (slices) — potężna cecha Perla, pozwalająca na natychmiastowe wyodrębnienie lub przypisanie grupy elementów z tablicy lub hasha w jednej operacji. Mechanizm wycinków istnieje prawie od pierwszych wersji Perla, wspiera składnię podobną do języka Python, ale ma własne cechy wykonania i kontekstu.
Problem:
Główna trudność z wycinkami: rozróżnianie wycinków-list tablic i hashy, ich kontekst skalarowy/listowy, „cienkie” niuanse przy przypisywaniu przez wycinki (szczególnie, jeśli przypisanie następuje do tych samych tablic lub hashy, lub używane są powtarzające się indeksy). Ważny punkt — jeśli z wycinkami aktualizujesz strukturę, łatwo przypadkowo uzyskać nieoczywisty wynik z powodu automatycznej ekspansji listy.
Rozwiązanie:
Używaj wycinków tylko świadomie. W razie potrzeby zrób kopię danych — użyj jawnego klonowania listy. Nie pozwól na nakładanie się przy odczycie i zapisie oraz wyraźnie zwracaj uwagę na kontekst skalarowy/listowy, jeśli wycinek jest używany jako argument funkcji lub elementu w wyrażeniu.
Przykład kodu:
my @array = (10, 20, 30, 40, 50); my @slice = @array[1, 3]; # (20, 40) @array[0, 2] = (100, 300); # @array teraz (100, 20, 300, 40, 50) my %hash = (foo => 1, bar => 2, baz => 3); my @vals = @hash{"foo", "baz"}; # (1, 3)
Kluczowe cechy:
Pytanie z pułapką 1: Czy można wziąć "skalarną" wartość z wycinka @array[2, 4] jako $val = @array[2, 4]?
Nie, $val w tym przypadku będzie równe liczbie elementów (długości listy), a nie wartości jednego elementu. Prawidłowo odwołuj się do poszczególnych elementów właśnie przez pojedyncze indeksy: $array[2].
Pytanie z pułapką 2: Jeśli w wycinku są powtarzające się indeksy, co jest zapisywane?
Sekwencyjne przypisywanie: wykonywane jest przypisanie dla każdego indeksu z lewej do prawej, ostatni wygrywa. Na przykład:
@array[0,0] = (1,2); # $array[0] == 2
Pytanie z pułapką 3: Czy można przypisywać wycinki z różną ilością elementów z prawej i lewej?
Można, jeśli z prawej mniej, pozostałe otrzymają undef. Jeśli więcej — nadmiarowe są ignorowane. Zwykle to źródło trudno wykrywalnych błędów.
Programista przypisuje wartości: @array[2, 3] = ("foo");
Oczekiwał, że oba elementy otrzymają "foo", ale $array[3] stał się undef.
Zalety:
Wady:
Używa funkcji map do mapowania wartości: @array[2, 3] = map { "foo" } (2, 3);
Zalety:
Wady: