Beefy Boxes and Bandwidth Generously Provided by pair Networks
Just another Perl shrine
 
PerlMonks  

Re^3: Declaring with my, assigning, and testing in same line (attributes)

by LanX (Saint)
on Dec 12, 2015 at 21:24 UTC ( [id://1150137]=note: print w/replies, xml ) Need Help??


in reply to Re^2: Declaring with my, assigning, and testing in same line (attributes)
in thread Declaring with my, assigning, and testing in same line

Thanks I started experimenting myself after you messaged me.

As said you'll need to tie cause Attributes happen at compile time and you have to intercept the assignment in STORE.

(didn't know about EXTEND till now)

I'm fine with using tie as long as I can untie when I'm done. Otherwise the penalty for this syntactic sugar would be to huge.

I took a simpler case, tieing a scalar, and trying to use untie $$self within STORE {}. Didn't work. (probably because dereferencing isn't allowed for untie or scope restrictions)

IMO as long we can't automatically untie, this approach shouldn't be used.

update

seems liked I didn't realy understood Tie::StdScalar yet

update
this approach with autotieref

use Attribute::Handlers autotieref => { Selfish => Tie::Selfish };

should provide the necessary reference to the tied structure, so that untieing becomes possible.

Cheers Rolf
(addicted to the Perl Programming Language and ☆☆☆☆ :)
Je suis Charlie!

Replies are listed 'Best First'.
Re^4: Declaring with my, assigning, and testing in same line (attributes)
by choroba (Cardinal) on Dec 12, 2015 at 21:58 UTC
    You can tie in the attribute handler, so you can untie there, too. So, a closure sent as an extra argument to the constructor works:
    #!/usr/bin/perl use warnings; use strict; use feature qw{ say }; { package Array::Nonempty::Attr; use Attribute::Handlers; sub Nonempty :ATTR(ARRAY) { my $referer = $_[2]; tie @$referer, 'Array::Nonempty', sub { untie @$referer } } } { package Array::Nonempty; use Tie::Array; use parent -norequire => 'Tie::StdArray'; use Carp; sub CLEAR { my $self = shift; $self->[0] = []; } sub TIEARRAY { my ($class, $untie) = @_; bless [ [], $untie ], $class } sub EXTEND { my ($self, $size) = @_; croak "Cannot be empty" if 0 == @{ $self->[0] } && 0 == $size; $self->SUPER::EXTEND($size); # Prevent "untie attempted while 1 inner references still exis +t" my $untie = $self->[1]; undef $self; $untie->() } } use parent -norequire => 'Array::Nonempty::Attr'; my %hash_ok = ( answer => 42 ); my %hash_empty = (); my @keys_ok :Nonempty = keys %hash_ok; say tied(@keys_ok) // 'not tied'; say for @keys_ok; my @keys_empty :Nonempty = keys %hash_empty;
    ($q=q:Sq=~/;[c](.)(.)/;chr(-||-|5+lengthSq)`"S|oS2"`map{chr |+ord }map{substrSq`S_+|`|}3E|-|`7**2-3:)=~y+S|`+$1,++print+eval$q,q,a,
      nice! :)

      see

      use Attribute::Handlers autotieref => { Selfish => Tie::Selfish };

      for another way for untie to access the varref

      Cheers Rolf
      (addicted to the Perl Programming Language and ☆☆☆☆ :)
      Je suis Charlie!

Re^4: Declaring with my, assigning, and testing in same line (attributes)
by LanX (Saint) on Dec 13, 2015 at 14:53 UTC
    > I'm fine with using tie as long as I can untie when I'm done. Otherwise the penalty for this syntactic sugar would be to huge.

    At second thought this is a too limited technique... consider

    while(1) { my $x :check = some_call(); }

    The check would be done only once, so in this case I'd clearly prefer a functional approach

    while(1) { check {RULE} my $x = some_call(); }

    Using attributes is a pretty way to apply ties, but most use cases I can think of combining this with untie are limited to debugging.

    > > > And for completeness , I'm sure you could also use variable :attributes for such checks.

    Wrong I was, young padawan. ;-)

    Cheers Rolf
    (addicted to the Perl Programming Language and ☆☆☆☆ :)
    Je suis Charlie!

      The check would be done only once
      My tests show otherwise:
      #!/usr/bin/perl use warnings; use strict; use feature qw{ say }; use Syntax::Construct qw{ // }; { package Array::Nonempty; use Tie::Array; use parent -norequire => 'Tie::StdArray'; use Carp; sub CLEAR { my $self = shift; $self->[0] = []; } sub TIEARRAY { my ($class, $untie) = @_; bless [ [], $untie ], $class } sub EXTEND { my ($self, $size) = @_; croak "Cannot be empty" if 0 == @{ $self->[0] } && 0 == $size; $self->SUPER::EXTEND($size); # Prevent "untie attempted while 1 inner references still exis +t" my $untie = $self->[1]; undef $self; untie @$untie; } } { package UNIVERSAL; use Attribute::Handlers autotieref => { Nonempty => 'Array::Nonemp +ty' }; } my @list = 1 .. 5; for (1 .. 10) { my @check :Nonempty = @list; shift @list; say tied(@check) // 'not tied'; say "@check"; }
      Wrong I was, young padawan. ;-)
      There are ways how not to be wrong.
      ($q=q:Sq=~/;[c](.)(.)/;chr(-||-|5+lengthSq)`"S|oS2"`map{chr |+ord }map{substrSq`S_+|`|}3E|-|`7**2-3:)=~y+S|`+$1,++print+eval$q,q,a,
        Interesting...

        I had the model for CODE attributes in mind which happen at compile time:

        (excerpt from attributes )

        3. Code: package X; sub foo : lvalue ; Effect: use attributes X => \&foo, "lvalue";

        That's why Attribute::Handlers is putting such emphasis onto the compilation phase when the association happens.

        but LEXICAL attributes seem to call import with each declaration at run-time (which is consistent with the fact that my has a compile and a run-time effect.)

        2. Code: package Felis; my $cat : Nervous; Effect: use attributes (); attributes::->import(Felis => \$cat, "Nervous");

        maybe Attribute::Handlers should be clearer about this?

        > There are ways how not to be wrong.

        (A disturbance in the Force happens)

        Now more potential in using attributes I see ... ;-) ¹

        Cheers Rolf
        (addicted to the Perl Programming Language and ☆☆☆☆ :)
        Je suis Charlie!

        update

        ¹) to be more specific ... this behaviour means that the untie happens almost immediately after the tie, i.e. the potential for possible ugly side effects is practically zero.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://1150137]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others taking refuge in the Monastery: (5)
As of 2024-03-29 11:12 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found