this thread is 6 years old; nevertheless, i can't make each() work on a tied hash :(

it is clear from the perltie documentation that the implementaion of each() is via FIRSTKEY and NEXTKEY. if that is so, then they must return a list in list context.

witness each documentation:

When called in list context, returns a 2-element list consisting of the key and value for the next element of a hash, so that you can iterate over it. When called in scalar context, returns only the key for the next element in the hash.

(emphasis mine)

if the each() documentation is true, then FIRSTKEY/NEXTKEY simply must return a list in list context.

and they do, but only if the return value of each() returned directly.

witness this example code:

use warnings; use strict; $\ = $/ = "\n"; sub ifdef { defined ($_[0]) ? $_[0] : ifdef($_[1], 'undef'); } ################################################## # # return each directly # package TIED_HASH_1; use Tie::Hash; our @ISA = qw(Tie::StdHash); sub FIRSTKEY { print "TIED_HASH_1 FIRSTKEY " . (wantarray ? "array" : "scalar"); my $a = scalar keys %{$_[0]}; return each %{$_[0]}; } sub NEXTKEY { print "TIED_HASH_1 NEXTKEY " . (wantarray ? "array" : "scalar"); return each %{$_[0]}; } ################################################## # # return each INdirectly # package TIED_HASH_2; use Tie::Hash; our @ISA = qw(Tie::StdHash); sub FIRSTKEY { print "TIED_HASH_2 FIRSTKEY " . (wantarray ? "array" : "scalar"); my $a = scalar keys %{$_[0]}; my ($x,$y) = each %{$_[0]}; print "x='$x' y='$y'"; # note $x and $y are fine return ($x, $y); } sub NEXTKEY { print "TIED_HASH_2 NEXTKEY " . (wantarray ? "array" : "scalar"); my ($x,$y) = each %{$_[0]}; print "x='$x' y='$y'"; # note $x and $y are fine return ($x, $y); } ################################################## # package main; my %h_untied; my %h_tied_1; my %h_tied_2; tie %h_tied_1, 'TIED_HASH_1'; tie %h_tied_2, 'TIED_HASH_2'; $h_untied{unt_a}=11; $h_untied{unt_b}=22; $h_tied_1 {t_1_a}=11; $h_tied_1 {t_1_b}=22; $h_tied_2 {t_2_a}=11; $h_tied_2 {t_2_b}=22; my ($k, $v); my @res; print "-------------------- untied hash works fine"; ($k, $v) = each %h_untied; print "k='$k' v='$v'"; ($k, $v) = each %h_untied; print "k='$k' v='$v'"; print "-------------------- tied hash returning each's return directly + works fine"; ($k, $v) = each %h_tied_1; print "k='$k' v='".ifdef($v)."'"; ($k, $v) = each %h_tied_1; print "k='$k' v='".ifdef($v)."'"; print "-------------------- tied hash returning its own list is brok"; ($k, $v) = each %h_tied_2; print "k='$k' v='".ifdef($v)."'"; ($k, $v) = each %h_tied_2; print "k='$k' v='".ifdef($v)."'";

Output:

-------------------- untied hash works fine k='unt_b' v='22' k='unt_a' v='11' -------------------- tied hash returning each's return directly works +fine TIED_HASH_1 FIRSTKEY scalar k='t_1_b' v='22' TIED_HASH_1 NEXTKEY scalar k='t_1_a' v='11' -------------------- tied hash returning its own list is brok TIED_HASH_2 FIRSTKEY scalar x='t_2_b' y='22' k='22' v='undef' TIED_HASH_2 NEXTKEY scalar x='t_2_a' y='11' k='11' v='undef'

you can see that each() called on TIED_HASH_2 simply does not work.

The only explanation i can see for this is that each() uses its own wantarray; some kind of wantarray_special_for_each or something.

but i come to the monks seeking wisdom because maybe there's something else going on here i can't see.

UPDATE: (forgot to include output of this code. 1am postings come with some risks ;) and fixed slight code bug)


In reply to Re: (FIRST|NEXT)KEY in context by johnvk
in thread (FIRST|NEXT)KEY in context by jweed

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.