Beefy Boxes and Bandwidth Generously Provided by pair Networks
Clear questions and runnable code
get the best and fastest answer
 
PerlMonks  

Re: Getting for() to accept a tied array in one statement

by LanX (Saint)
on Apr 16, 2019 at 11:25 UTC ( [id://1232644]=note: print w/replies, xml ) Need Help??


in reply to Getting for() to accept a tied array in one statement

> However, condensing the above syntax to what I want is still not possible:

waht?

please provide a test case clearly demonstrating what you want and what not.

Cheers Rolf
(addicted to the Perl Programming Language :)
Wikisyntax for the Monastery FootballPerl is like chess, only without the dice

  • Comment on Re: Getting for() to accept a tied array in one statement

Replies are listed 'Best First'.
Re^2: Getting for() to accept a tied array in one statement
by perlancar (Hermit) on Apr 16, 2019 at 13:12 UTC

    for (tie @ary, "My::Class", "some", "contents") { ... } # NOPE

    does not work because for() gets a single-element list which is the tied object, not the tied array itself.

    for (do { tie @ary, "My::Class", "some", "contents"; @ary }) { ... } #NOPE

    does not work because for() gets an ordinary (non-magical) list of values. All the values from the tied array have been FETCH-ed. I need to iterate over the tied array so code inside the loop block and FETCH are executed once for each element, together.

    tie @ary, "My::Class", "some", "contents"; for (@ary) { ... }

    works, but I want something more similar to:

    for (wrapper(@ary)) { ... }

    where @ary is an ordinary array or a list of values.

      > because for() gets an ordinary (non-magical) list of values.

      That's not how I understand the output. It seems FETCHSIZE is only called once, but each element is fetched right before the iteration:

      #! /usr/bin/perl use warnings; use strict; use feature qw{ say }; { package My; use Tie::Array; use parent -norequire => 'Tie::StdArray'; sub TIEARRAY { warn "TIE: @_\n"; my $class = shift; bless [@_], $class } sub FETCHSIZE { warn "SIZE: @_\n"; return scalar @{ $_[0] } } sub FETCH { warn "FETCH: @_\n"; my ($ar, $idx) = @_; my $e = $ar->[$idx]; return ++$e } } for my $e (do { tie my @ar, 'My', qw( a b c ); @ar } ) { say "MAIN: $e"; }
      Output:
      TIE: My a b c SIZE: My=ARRAY(0x21eff40) FETCH: My=ARRAY(0x21eff40) 0 MAIN: b FETCH: My=ARRAY(0x21eff40) 1 MAIN: c FETCH: My=ARRAY(0x21eff40) 2 MAIN: d

      for my $e (@ar), on the other hand, calls FETCHSIZE before each FETCH.

      map{substr$_->[0],$_->[1]||0,1}[\*||{},3],[[]],[ref qr-1,-,-1],[{}],[sub{}^*ARGV,3]

        Yup, I was referring to for(), where an additional FETCHSIZE is invoked for each iteration, which is useful in the case where we want to size to be dynamic/growing.

        It seems FETCHSIZE is only called once, but each element is fetched right before the iteration:

        That's correct. for (@a) iterates over the indexes as if you had done for (0..$#a). This differs from for ((), @a), which retrieves the contents of @a up front.

      This:

      for (tie @ary, "My::Class", "some", "contents";) { ... }

      is exactly what you should NOT be doing

      Read: Tying-Arrays: If someone outside the class tries to dereference the object returned (doubtless thinking it an ARRAY ref), they'll blow up. This just goes to show you that you should respect an object's privacy.

      FETCH and FETCHSIZE are exactly for that you can: 'respect an object's privacy':

      Something like this:

      my $aryt = tie @ary, "My::Class", "some", "contents"; @ary = ... ; for (0..($aryt->FETCHSIZE-1)) { do-something($aryt->FETCH($_)); }

        But isn't the whole point of tie that one can use the tied array as if it were a normal array and all the magic happens without ever calling the classes' methods explicitly?

      you can't bend for into an object's method.

      Perl != Python

      the closest to a drop in replacement is maybe a customfunction sub xfor (&&) :

      xfor {@arr} sub { ...};

      Cheers Rolf
      (addicted to the Perl Programming Language :)
      Wikisyntax for the Monastery FootballPerl is like chess, only without the dice

        Didn't hdb just do that? :-)

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others having a coffee break in the Monastery: (3)
As of 2024-04-25 17:56 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found