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

Now imagine that the LVALUE sub below (with better syntax) was a builtin and the TIESCALAR was invisible--generated automatically by the compiler.

#! perl -slw use strict; package Sensible; sub TIESCALAR { my( $class, $fetch, $store ) = @_; no warnings 'redefine'; *FETCH = *FETCH = $fetch; *STORE = *STORE = $store; bless [], $class; } sub LVALUE (&&) : lvalue { my( $fetch, $validate ) = @_; tie my $lvalue, 'Sensible', $fetch, $validate; $lvalue; } sub new { my( $class, $init ) = @_; return bless \$init, $class; } sub attr : lvalue { my( $self, $start, $len ) = @_; $start ||= 0; $len ||= length ${ $_[ 0 ] }; LVALUE { substr( $$self, $start, $len ) } sub{ warn( 'Bad value' ), return unless $_[ 1 ] =~ m[^[a-z ]+$]; substr( $$self, $start, $len ) = $_[ 1 ]; }; } package main; my $sensible = Sensible->new( 'The quick brown fox jumps over the lazy + dog' ); print $sensible->attr; $sensible->attr( 10, 5 ) = 'green'; print $sensible->attr; $sensible->attr( 20 ) = 'did not see the paint tin'; print $sensible->attr; $sensible->attr( 10, 5 ) = 'ORANGE'; print $sensible->attr; __END__ [ 2:03:26.03] P:\test>425402-2 The quick brown fox jumps over the lazy dog The quick green fox jumps over the lazy dog The quick green fox did not see the paint tin Bad value at P:\test\425402-2.pl line 31. The quick green fox did not see the paint tin

Note how there is no need for a separate tie class for every different validation routine. Just one for scalars, one for arrays, and one for hashes.

Note how all the code is in a single place. And how the validation code has full access to the entire environment of the original sub. No need to pass everything required, it is all available via closure.

One additional keyword and some (a little) extra code generated--by the compiler, not the programmer.

As you can see, you needn't feel silly. I was there a long time ago.


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

Replies are listed 'Best First'.
Re^16: Assignable Subroutines
by Aristotle (Chancellor) on Jan 27, 2005 at 17:46 UTC

    That doesn't work if you have several different scalar properties in the same class which require different forms of validation, nor does it work if the same lvalue is accessed multiple times at once (a trivially constructible circumstance).

    Makeshifts last the longest.

      It is a P5 simulation, without the benefit of P6 lexical subroutines. How do you think this will work?

      class ....{ my sub thingie1 is rw { return my $var is Proxy( for => $hidden_var, FETCH => { ... }, STORE => { ... }, TEMP => { ... }, ... ); } my sub thingie2 is rw { return my $var is Proxy( for => $hidden_var, FETCH => { ... }, STORE => { ... }, TEMP => { ... }, ... ); } ... }

      And, if the ties involved in the my suggestion above, are generated by the compiler, what is to stop them from using the same mechanism as this Apo6 code uses to isolate the tie for one attribute from the tie for another?

      The only difference is who writes the code and where. One is inline, clear and trivial with the compiler doing all the drudge work.

      The other is, out-of-band, complex, obscure and repetative, requiring the programmer to code lots of little code blocks instead of a simple, inline block of code.


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

        I'd imagine something closer to

        return my $var but :setter { ... };

        where $var is probably accessible in the setter as the current topic.

        Makeshifts last the longest.