in reply to Re^5: Assignable Subroutines
in thread Assignable Subroutines

If it's just combining two setters into one call, ...

How on earth did you reach that conclusion?

This syntax is standard perl and works now. Is my use of [] so confusing?

You've never used

substr( $buffer, $n, $m ) =~ s[this][that]g;
?

Note, this might be direct access to an internal buffer, but it could equally be a subset of a bigger than memory file, or a BLOB queried from a DB.

The problem is that, you cannot do anything afterwards.

So, for example, in the latter case, you could not arrange for the modified BLOB to be written back to the DB.

Of course, the alternative syntax is:

my $temp = $obj->get_thing( 15000, 20000 ); $temp =~ s[this][that]g; $obj->set_thing( 15000, 200000, $temp );

which besides the:

  1. inconvenient notation;
  2. requirement for a temporary variable;
  3. the inefficiency of copying large chunks of data around unnecessarially.
  4. The need for two nearly identical pieces of code.
  5. and the potential for someone to come along and stick some other lines of code between two halves of what should be an "atomic" operation.

Did you notice the typo?


Examine what is said, not who speaks.
Silence betokens consent.
Love the truth but pardon error.

Replies are listed 'Best First'.
Re^7: Assignable Subroutines
by Tanktalus (Canon) on Jan 25, 2005 at 16:41 UTC

    I had the wierdest of thoughts (ain't TMTOWTDI wonderful?) ...

    sub update_thing { my ($self, $x, $y, $u) = @_; if (ref $u and UNIVERSAL::isa($u, 'CODE')) { # use temp to keep the $u function from changing $_[0] ;-) my $val = $self->{cell}[$x][$y]; $u = $u->($val); } # validate $u. if ($is_valid) { $self->{cell}[$x][$y] = $u; }

    called sorta like:

    $obj->update_thing(15000, 20000, sub { $_[0] =~ s[something][else]g; + $_[0] } );

    No, not better than $obj->thing(15000,2000) =~ s[something][else]g. But a bit better than the other ideas going around, maybe? :-) If not better, at least different...

      It's a fine notion but it has it's problems.

      You now, need to code

      • a get_thing() method;
        print $obj->thing;
      • a set_thing() method;
        $obj->thing = 'someting';
      • a update_thing() method;
        $obj->thing =~ s[this][that]g;
      • a return_list_of_matched_subthings() method;
        my @subthings = $obj->thing =~ m[subthing]g;
      • a return_count_of_subthings() method;
        my $count = $obj->thing =~ m[subthing]g;
      • a get_subthing_iterator() method;
        while( $obj->thing =~ m[subthing]g ) { last if substr( $obj->thing, pos( $obj->thing ) - 22, 22 ) eq 'This is *the* subthing'; }

        (Oh! And a substr_thing() method;)

      • a preincr_thing() method;
        $obj->thing++;
      • A postincr_thing() method;
        ++$obj->thing;
      • (pre/post decr etc. etc)

      And all the others that you effectively get for free with a single lvalue method.

      All that is missing is a convenient way to validate the assignment.


      Examine what is said, not who speaks.
      Silence betokens consent.
      Love the truth but pardon error.
Re^7: Assignable Subroutines
by demerphq (Chancellor) on Jan 25, 2005 at 16:32 UTC

    So it would seem you have answered my question: do the arguments get passed to both the setter and the getter or does only one of them get them. On reflection i suppose "both of them" is the obvious choice....

    ---
    demerphq

Re^7: Assignable Subroutines
by perrin (Chancellor) on Jan 25, 2005 at 17:44 UTC
    How on earth did you reach that conclusion?

    It's confusing syntax. I thought you were assigning the return value of running the regex on the return value of your method call.

    You've never used substr( $buffer, $n, $m ) =~ s[this][that]g; ?

    No, I find that hard to read. I would use a temp variable there. Your alternative syntax example looks much clearer to me. I expect that the inefficient copying you're worried about would happen either way.

      I expect that the inefficient copying you're worried about would happen either way.

      Actually, no. With the current implementation, the lvalue method gives the substitution operator direct access to the underlying memory. Indeed, it this desire to retain this efficient, direct access that is behind TimToady's reluctance to change the current mechanism for one that would allow validation. I like the ability to achieve that efficiency, but not so much that I wouldn't give it up for the ability to verify the assignment.

      But the efficiency is only one of the list of benefits I outlined. Most of the others, including 2 or 3 that I thought would be very close to your heart--those that prevent the possibilities of errors being introduced--are much more relevant and desirable.

      I fail to understand how you can find: $obj->thing =~ s[this][that]g;

      confusing, but not $string =~ s[this][that]g;?

      But maybe the question is not how, but why!


      Examine what is said, not who speaks.
      Silence betokens consent.
      Love the truth but pardon error.
        $string =~ s[this][that]g operates on a variable. It isn't the easiest thing to read, but it's been around so long that we've all gotten used to it. The syntax you're proposing has too much going on in one line. It's not even operating on the method, but on the return value of the method. And then does it call the method again to set the new value, or do some kind of implicit referencing? It's not obvious.

        I didn't respond to the other benefits you listed because all of them less important than readability. The current syntax doesn't seem cumbersome to me.