in reply to Perl level control of hash iterators

No. You'd have to do this in XS and outside of the published API. Even when you're in XS the published API just tells you to reset the iterator prior to using it. I suppose what you could do is track which key you were currently at, let the iterator get perturbed then reset it and advance it til you find the same key again.

⠤⠤ ⠙⠊⠕⠞⠁⠇⠑⠧⠊

  • Comment on Re: Perl leve control of hash iterators

Replies are listed 'Best First'.
Re^2: Perl leve control of hash iterators
by bsb (Priest) on Feb 28, 2007 at 04:05 UTC
    Just to clarify (for all respondants) I'm investigating a bug in Data::Rmap where the following loops off forever:
    perl -MData::Rmap=rmap_hash -le 'rmap_hash {print keys %{$_->{a}} } ({ +a=>{1,2}})'
    I'm not certain, but I suspect that the keys call interacts with this line, from Data::Rmap:
    push @return, $self->_rmap($_) for values %$_;
    Since the module is for general use, XS or tie-ing aren't really options. Also, $_ is aliased during the callback so that things, including hashes can be changed (sometimes leading to different disasters). This further constrains the solution space.

    Thanks for your tips,

    Brad

    Update: I think autovivification is to blame

    # added exists check perl -MData::Rmap=rmap_hash -le 'rmap_hash {print keys %{$_->{a}} if e +xists $_->{a} } ({a=>{1,2}})' 1

      Well... you'd probably better modify whatever you were given so it is read-only so the iterators *can* be reset and then you'd better do the reset/iterate-to-orig thing. Or... avoid ever using each() in Data::Rmap or take the "call arbitrary code" part out of Rmap or disallow using hashes.

      ⠤⠤ ⠙⠊⠕⠞⠁⠇⠑⠧⠊

      push @return, $self->_rmap($_) for values %$_;
      Hmm, if you do this another way, you must be able to avoid the problem:
      push @return, map { $self->_rmap($_) } values %$_;
      Here, values is finished before the map even starts.

      However... you won't have a problem in the original unless the values is traversed lazily. You never know...