in reply to Re: Using exists to check element in array
in thread Using exists to check element in array

This won't help with existing undefined values.

Exist is the logical choice in his use case, and he asked for the rationale.

Cheers Rolf
(addicted to the Perl Programming Language :)
see Wikisyntax for the Monastery

  • Comment on Re^2: Using exists to check element in array

Replies are listed 'Best First'.
Re^3: Using exists to check element in array
by ikegami (Patriarch) on Jan 29, 2024 at 19:03 UTC

    and he asked for the rational.

    Hasn't that been answered already?

    It's because exists $a[i] doesn't really check if the element exists in the array. It's not sufficient for the element to be part of the array; the pointer in the array buffer must be something other than NULL.

    For example,

    my @a; $a[1] = undef; $a[2] = 0; $a[3] = 7;
    Element of the arrayexistsdefinedTrue
    $a[0]YesNoNoNo
    $a[1]YesYesNoNo
    $a[2]YesYesYesNo
    $a[3]YesYesYesYes
    $a[4]NoNoNoNo

    It might also be warning of problems with using NULL as a special value. I suspect Perl is quite consistent at keeping NULL elements NULL, but there might be surprise cases (for (@a)? for ((), @a)? f(@a)?)

    Update: Replaced some uses of "exists".

      To misquote Bill Clinton:

      "It depends if your meaning of exist exists."

      ;)

      Your table shows exactly a consistent behavior to exists when used with hashes. Unset values just don't exist.

      $a[0] was never set, hence it doesn't exist.

      I wasn't sure what you and sectokia meant with null-pointer, apparently it's the C-value of unset "gap" values¹ in the underlying C-array.

      But those exist only on the C level, not logically in Perl.

      > but there might be surprise cases (for (@a)? for ((), @a)? f(@a)?)

      I don't understand, probably above my expertise.

      Cheers Rolf
      (addicted to the Perl Programming Language :)
      see Wikisyntax for the Monastery

      ¹) with an index smaller than the maximal index of a set value

        Your table shows exactly a consistent behavior to exists when used with hashes.

        No, it's not consistent with hashes.

        $ perl -e' my %h = ( a => 4, c => 6 ); printf( "exists %s return false for elements found in a hash.\n", ( grep { !exists( $h{$_} ) } keys %h ) ? "can" : "didn\x27t" ); my @a; $a[0] = 4; $a[2] = 6; printf( "exists %s return false for elements found in an array.\n", ( grep { !exists( $a[$_] ) } keys @a ) ? "can" : "didn\x27t" ); ' exists didn't return false for elements found in a hash. exists can return false for elements found in an array.

        The very existence of this inconsistency is reason enough for a warning.

        $a[0] was never set, hence it doesn't exist.

        No, that means it wasn't set. Setting or not setting has nothing to do whether an element is found in an array or not, and with what exists returns.

        exists can obviously return false for elements that were never set, but it can also return true for such elements as the following demonstrates:

        $ perl -Mv5.14 -e'my @a; \$a[0]; say exists( $a[0] ) || 0;' 1

        Your implication that exists checks whether an element was set or not is incorrect. As I already mentioned, exists checks if an element is within the array and if it isn't NULL.

        I don't understand, probably above my expertise.

        These are things that might unintentionally change replace the NULL with a (pointer to a) scalar. I didn't test.

        Upd: I just did and they don't. But \$a[0] does, as shown above.

Re^3: Using exists to check element in array
by ikegami (Patriarch) on Jan 29, 2024 at 18:47 UTC

    It will help if undef isn't an acceptable value, which is a common scenario.

    I should have qualified my answer, but I thought the OP said they were storing numbers. Those are the keys, though. woops.