On Fri, Jul 12, 2002 at 10:39:08AM +0200, Bodo Eing wrote:
> On 11 Jul 2002, at 15:02, Jeff Zucker wrote:
>
> > Pomin Wu wrote:
> >
> > > When accessing CSV with AnyData as a tie hash, I found
> > > that although the C<while (my $row = each %$table)> syntax
> > > is valuable, it C<last> as soon as I try to modify the
> > > table inside the loop, for ex. C<delete $table->{key};>.
> > > Or have I missed something?
> >
> >
> > Not sure what you mean. This works:
> >
> > use AnyData;
> > my $table = adTie( 'CSV', ["id,phrase\n1,foo\n2,bar\n3,baz"] );
> > while (my $row=each %$table) {
> > delete $table->{$row->{id}}
> > if $row->{id}<3 and $row->{phrase} ne 'bar';
> > }
> >
> > But if all you want to do is delete a set of rows, you don't need the
> > while loop, you can just do something like this which accomplishes the
> > same thing as the while loop above:
> >
> > delete $table->{{id=>'< 3',phrase=>'ne bar'}};
> >
> > If I've misunderstood your question, please send an example of the
> > offending code.
> >
> > --
> > Jeff
> >
>
> Although it may work for this particular case, I consider it critical
> to edit hashes while iterating over them with the while/each
> construct. Although deleting is "officially" allowed (see perlfaq4)
> for conventional hashes since perl5, and changing the current value
> is also possible, this can get you into trouble with tied hashes
> (e.g., changing the values of a hash tied to MLDBM during iteration
> with while/each can bomb you into an infinite loop). In general, I
> think that while/each is for fast read-only access, and for/keys for
> editing purposes.
>
> Bodo
>
>
>
Yes, I tried out some code as suggested. It seems the foreach/keys
construct does not have this problem. This is the result:
use AnyData;
my $table = adTie 'CSV', ["name,class,total\nSam,normal,18\nMary,normal,278"]
or die "can't adTie: $!";
while (my $row = each %$table) {
print "$row->{name}\n";
# this would stop after 'Sam'
$table->{{ name => $row->{name} }} = {total => 1};
# this also
#$row->{name} .= '0';
#$table->{$row->{name}} = $row;
# but this works
#delete $table->{$row->{name}};
}
foreach my $row (keys %$table) {
print "$row->{name}\n";
# this works
$table->{{ name => $row->{name} }} = {total => $row->{total} + 1};
# this also
#$row->{name} .= '0';
#$table->{$row->{name}} = $row;
# and of course this
#delete $table->{$row->{name}};
}
/pm5/