in reply to Re: optimization - exists should return a reference
in thread optimization - exists should return a reference

So what your saying is that because someone might do

print ${exists $foo{'bar'};

instead of

print $$_ if $_ = exists $foo{'bar'};

and get a runtime error something like Use of uninitialized value in scalar dereference ...

you would prevent anyone from benefiting from the advantages of using it properly?

Given that in the example above, the user has at least acknowledge that $foo{'bar'} may not exist by the very act of using exists, then that's seems analogous to, and a much less easy mistake to make than doing

print $foo{'bar'};

instead of

print $foo{'bar'} if exists $foo{'bar'}

currently, which also results in a runtime warning.

Isn't it kind of against the spirit of Perl's we ask you to read the warning signs rather than enforce them with a shotgun approach?


Examine what is said, not who speaks.

The 7th Rule of perl club is -- pearl clubs are easily damaged. Use a diamond club instead.

Replies are listed 'Best First'.
Re: Re: Re: optimization - exists should return a reference
by Zaxo (Archbishop) on Jan 15, 2003 at 18:32 UTC

    Yes, that's exactly what I'm saying.

    If exists is to return a reference, it should always return a reference. Code exists which says exists( $foo{'bar}) ? 'Exists' : 'Does not exist'. That code will break if exists returns a reference, because references always evaluate true.

    If what we get from exists is a reference, we should be able to treat is like any other reference. You seem to want to be able to assign from it and dereference the copy, but deny the ability to dereferencee it directly.

    Just how is that supposed to work?

    After Compline,
    Zaxo

      Sorry Zaxo. I know I'm being thick here, but if the entity being testing for existance doesn't exist, exists can't return a reference to it. And if it did return a "false reference", you wouldn't be able to do anything with it except test it for being false, so it should just return false, whether that is undef, 0, or '' makes no difference. As long as it returns false, then existing code like

      print exists( $foo{'bar'} ) ? 'Exists' : 'Doesn't exist';

      doesn't break.

      I'm sure I missing the salient point here, but I can't see where.


      Examine what is said, not who speaks.

      The 7th Rule of perl club is -- pearl clubs are easily damaged. Use a diamond club instead.

      Right now, we can only use exists as a boolean. The suggestion is to extend it so that when the value returned is true that value is itself useful.

      Assume for a minute that the hypothetical reference-that-evaluates-to-false-in-boolean-context actually could be returned... what use would it be to dereference it anyway?

      If you really wanted something like that, you could forge it yourself:

      my $bar = ${exists($foo{bar}) || \undef};

      -sauoq
      "My two cents aren't worth a dime.";
      

      "If exists is to return a reference, it should always return a reference."

      I don't know about that. Let's say we're looking at exists($foo{'bar'}). So, if $foo{'bar'} exists, exists returns a reference to it. Otherwise, it returns undef or an empty string, or 0 or whatever the hell. Something that's false in a boolean context. One potential problem, as you point out, is if someone tries to dereference the result without checking to see if it's true first. (I'll assume for the time being that it's out of the question to change the way references evaluate in boolean context :o)

      I would say that checking for the existance of the value returned by exists is pretty natural. For instance the example put forward by BrowserUK:

      use strict 'refs'; print ${exists $foo{'bar'}};

      would yield Can't use an undefined value as a SCALAR reference or something of the like. This would be an example of bad coding: using a value without being sure that there is a value. It's really no different from: The same mistake is made (and the same error potentially generated) as if the following were written:

      use strict 'refs'; print ${$foo{'bar'}};

      This would yield the same error. Whereas one 'right' way to do the same thing would be:
      One 'right' way to use the reference from the proposed exists would be:

      use strict 'refs'; print ${exists $foo{'bar'} || \"" };

      ...perhaps substituting a reference to a default value or somesuch for the \"". What I'm saying is that this puts responsibility on the programmer to make sure she doesn't try to dereference anything undefined or whatever. If she wants to be able to do stuff like print ${exists $foo{'bar'}} she's not going to use strict. For the rest of us, we get added functionality for exists that doesn't break existing code.

      Update: The crux, in my mind, of why print ${exists $foo{'bar'}} doesn't make sense just finally came to me in actual words: it's like writing print ( if ($foo{'bar'}) ), or print ( $foo > $bar ). It's a boolean test, which is not designed to stand alone. Conceptually, exists exists to choose between two options.

      Update: Aristotle pointed out some ambiguity in the way I phrased some stuff. Also, I noticed that in my first paragraph I had written exists $foo instead of exists $foo{'bar'}.


      LAI
      :eof
        print ${exists $foo{'bar'}}; # ... print ${$foo{'bar'}};
        These differ. The former would print the value of $foo{bar}, the latter of ${$foo{bar}}.

        Makeshifts last the longest.