programowanieProgramista Backend Perl, Inżynier Danych (Perl), Programista Fullstack Perl

Jakie istnieją pułapki przy pracy z operatorem defined i jak poprawnie sprawdzać istnienie i niepustość wartości w różnych typach zmiennych Perl?

Zdaj rozmowy kwalifikacyjne z asystentem AI Hintsage

Odpowiedź.

Operator defined w Perl sprawdza, czy wartość jest zdefiniowana (czy nie jest undef). Ważne jest, aby rozróżniać:

  • Dla skalarów: defined($x) zwróci true, jeśli $x nie jest równe undef (niezależnie od wartości, nawet jeśli to pusty ciąg lub 0).
  • Dla hashy: defined($hash{$key}) sprawdza, czy wartość elementu jest zdefiniowana, ale nie gwarantuje, że sam klucz istnieje.
  • Dla tablicy: defined($array[$i]) — podobnie, element może być zdefiniowany, ale tablica może mieć różną długość.
  • Aby sprawdzić istnienie klucza w hashy, używa się exists.

Przykład:

my %h = (a => undef); if (exists $h{a}) { print "Klucz 'a' istnieje "; } if (defined $h{a}) { print "Klucz 'a' jest zdefiniowany "; } else { print "Klucz 'a' nie jest zdefiniowany "; }

Wynik:

Klucz 'a' istnieje
Klucz 'a' nie jest zdefiniowany

Pytanie z haczykiem.

Czym się różni exists $hash{$key} od defined $hash{$key} i kiedy sprawdzenie na defined dla hashy da nieoczekiwany wynik?

Odpowiedź: defined $hash{$key} sprawdza wartość, ale jeśli klucz nie istnieje, zwróci wartość nieokreśloną. Jeśli klucz istnieje, ale jego wartość to undef, defined zwróci false. Ale jeśli klucza nie ma — również false. Dlatego do sprawdzenia istnienia klucza zawsze używaj exists.

Przykład:

my %h = (foo => undef); if (defined $h{foo}) { ... } # false if (exists $h{foo}) { ... } # true

Przykłady rzeczywistych błędów z powodu braku znajomości szczegółów tematu.


Historia

W jednym projekcie sprawdzano flagę "gotowości" jako defined($status{$id}), i jeśli wartością była undef, uznawano zadanie za nieprzetworzone. Jednak klucze z undef były ważne, a sprawdzenie exists nie było — w konsekwencji część przetworzonych danych uruchamiano ponownie.


Historia

Programista importując dane z pliku, porównywał ciągi w ten sposób: if (defined $line && $line ne ''). Problem: czasami $line mógł być zerowym ciągiem '0'. Taki ciąg nie jest pusty, ale porównanie z defined (zamiast sprawdzenia ne '') prowadziło do utraty tych ciągów.


Historia

W dużym skrypcie Perl, który pracował z hashami, jedyną kontrolą istnienia elementu był defined — w wyniku tego dla kluczy o wartości undef pojawiały się błędy i brakujące dane w raportach.