6 votes

Should x < $foo < y read from $foo once or twice? Perl debates

8 comments

  1. spit-evil-olive-tips
    Link
    https://www.perl.com/article/magical-tied-scalars/ has a good intro to the Perl feature that makes this possible. Just the fact that they're described as "magical" is the first red flag, IMO......

    https://www.perl.com/article/magical-tied-scalars/ has a good intro to the Perl feature that makes this possible. Just the fact that they're described as "magical" is the first red flag, IMO...

    This seems like such an amazingly Perl-ish feature. By reading a variable's value, you're permitted to have arbitrary side effects, including modifying the internal state of the scalar class.

    Shockingly, allowing that leads to bizarre edge cases, like questions of whether evaluating the expression x < $foo < y should cause those side effects to happen twice.

    4 votes
  2. Crestwave
    Link
    Note that the expression is only evaluated once, so an ordinary subroutine/function would only execute once; however, the value can be fetched twice, which causes this problem for tied scalars....

    Note that the expression is only evaluated once, so an ordinary subroutine/function would only execute once; however, the value can be fetched twice, which causes this problem for tied scalars. Relevant documentation: https://perldoc.pl/5.31.11/perlop#Operator-Precedence-and-Associativity.

    3 votes
  3. [6]
    ClearlyAlive
    Link
    Obviously once. If I as the user wanted to insist on twice I’d write it twice.

    Obviously once. If I as the user wanted to insist on twice I’d write it twice.

    1 vote
    1. [5]
      Crestwave
      Link Parent
      Have you read through the issue? It seems that semantically, fetching it twice makes sense, but clearly that isn't what a user initially expects. However, tied variables also don't seem to be very...

      Have you read through the issue? It seems that semantically, fetching it twice makes sense, but clearly that isn't what a user initially expects. However, tied variables also don't seem to be very common, and they are usually idempotent; otherwise, you would have to be careful and aware of this kind of behavior, anyway. So it probably isn't something a beginner would touch.

      Also note that since it ends up as something like $x < $y && $y < $z (if everything is a scalar, that is), I'm guessing that $z won't be fetched if the left side is false. So with that in mind, it makes sense that $y should possibly be fetched twice, right?

      1. [4]
        ClearlyAlive
        (edited )
        Link Parent
        I’ve had a look yes. My view is primarily based on what the user knows and expects. In the user’s conception of the language tied variables have the following axiom: Everytime a tied variable is...

        Have you read through the issue?

        I’ve had a look yes.

        So it probably isn't something a beginner would touch.

        My view is primarily based on what the user knows and expects. In the user’s conception of the language tied variables have the following axiom:

        1. Everytime a tied variable is used it may mutate.

        The problem with the fetching twice is that it seems violates that axiom in the user's conception.

        Also note that since it ends up as something like $x < $y && $y < $z (if everything is a scalar, that is), I'm guessing that $z won't be fetched if the left side is false. So with that in mind, it makes sense that $y should possibly be fetched twice, right?

        Of course, technically it doesn't as you rightly point out. But this misses the UX issue in terms of how people read code. People will translate the above axiom into the following:

        1. Everytime a tied variable appears it may mutate.

        in their brains. That way whenever reading code they can see easily see how tied variables are changing. The current behaviour clearly violates that axiom and makes reading code harder. It's true, as developers we can expect them to be more aware of implementation details as compared to end-users, but still I think that because of how trivial the solution is: { temp = $y; $x < temp && temp < $z} we should change it to better suit these axioms.

        In general I believe that developers and users shouldn't need to worry about the underlying representation unless they really need to (e.g. speed optimisations), this doesn't strike me as one of those cases.

        1 vote
        1. [3]
          Crestwave
          Link Parent
          From the issue (an example is given in the thread I mention later): This is actually how it's documented, but temp would still be the tied object in the current implementation. Here's a discussion...

          Everytime a tied variable appears it may mutate.

          From the issue (an example is given in the thread I mention later):

          The number of times fetch is called is not dependent on the number of times that variable is mentioned (there are plenty of exceptions to that), it's dependent on the number of operations on it.


          but still I think that because of how trivial the solution is: { temp = $y; $x < temp && temp < $z} we should change it to better suit these axioms.

          This is actually how it's documented, but temp would still be the tied object in the current implementation. Here's a discussion on it (see the thread replies as well).

          The consensus seems to be to document this behavior better; would that not remove the element of surprise/confusion?

          1. [2]
            DrStone
            Link Parent
            Technically correct documentation is not sufficient for a situation where how things behave seems extremely obvious to a large portion of people, but will silently (and perhaps subtly) behave...

            The consensus seems to be to document this behavior better; would that not remove the element of surprise/confusion?

            Technically correct documentation is not sufficient for a situation where how things behave seems extremely obvious to a large portion of people, but will silently (and perhaps subtly) behave differently. Nobody is going to read the documentation before using. This is made worse when those expectations hold true in most situations. When a problem does arise, people aren't even going to consider that's the possible cause and read those specific docs.

            Like, if I was adding numbers as part of some business logic function and it was off only sometimes even even given the same inputs, I probably wouldn't ever think to read the documentation for +.

            1. Crestwave
              Link Parent
              I feel like using a non-idempotent tied scalar is enough of a gotcha that you would check out the documentation, and again, note that fetching a scalar mentioned once multiple times is not...

              I feel like using a non-idempotent tied scalar is enough of a gotcha that you would check out the documentation, and again, note that fetching a scalar mentioned once multiple times is not anything specific to this; I think the need for documentation is more for the perceived inconsistency between tied scalars and subroutines in this case.

              Also, chained comparisons are a mess in general; this circulated recently for Python.