As a good learning excercise, I am attempting to reimplement Tie::IxHash without looking at the source code. Certain things are bugging me though. FIRSTKEY and NEXTKEY are described in perltie thusly:

FIRSTKEY this This method will be triggered when the user is going to iterate through the hash, such as via a keys() or each() call. sub FIRSTKEY { carp &whowasi if $DEBUG; my $self = shift; my $a = keys %{$self->{LIST}};# reset each() iterator each %{$self->{LIST}} } NEXTKEY this, lastkey This method gets triggered during a keys() or each() iteration. It has a second argument which is the last key that had been accessed. This is useful if you're carrying about ordering or calling the iterator from more than one sequence, or not really storing things in a hash anywhere. For our example, we're using a real hash so we'll do just the simple thing, but we'll have to go through the LIST field indirectly. sub NEXTKEY { carp &whowasi if $DEBUG; my $self = shift; return each %{ $self->{LIST} } }

Going by the names of these functions, I would assume that they ought to return only the next key to use. The fact that they end with each, though, makes me wonder if they should behave as each actually does: that is, keys and values in list context, keys only in scalar context. If keys and values were only the other way around, I could return ($value, $key), because in scalar context left args are thrown away. Since that isn't the case, though, I'm forced to use wantarray. So far so good.

The problem, though, is the FIRSTKEY (and NEXTKEY) always seem to be called in scalar context. Here is my test code:

package Foo; sub TIEHASH { bless {}, shift; }; sub FIRSTKEY { wantarray ? print "Array\n" : print "Scalar\n" }; *NEXTKEY = *FIRSTKEY; sub FETCH { return }; package main; tie %me, Foo; () = each %me; scalar each %me; __END__ Scalar Scalar

The two conclusions that I can doraw from this are a) it only wants the keys, and thus is always called in scalar context, or b) that wantarray isn't always right in cases like these. My main idea for why this might be the case is evident in Overloading for List Context. Though that was with overloading, my concern is that perl internals which tie deals with don't do the context thing per-wantarray.

The only way that I could see dealing with b) in a way consistent with the docs but which doesn't use wantarry is to make a temp array and use each on that, but that's hackish and ugly.

Any other thgouhts on the dealio?



Who is Kayser Söze?
Code is (almost) always untested.

In reply to (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.