in reply to Are strings lists of characters?

package NeedsAName; sub TIEHASH { my ($class, $ref) = @_; return bless \$ref, $class; } sub FETCH { my ($self, $key) = @_; return substr $$$self, $key, 1; } sub STORE { my ($self, $key, $data) = @_; return substr($$$self, $key, 1) = $data; } sub CLEAR { my ($self) = @_; $$$self = ''; } sub DELETE { my ($self, $key) = @_: $self->STORE($key, ''); } sub EXISTS { my ($self, $key) = @_; return $key <= length $$$self; } sub FIRSTKEY { my ($self) = @_; return length $$$self ? 0 : undef; } sub NEXTKEY { my ($self, $lastkey) = @_ return length $$$self > $lastkey ? $lastkey + 1 : undef; } # tie %foo, 'NeedsAName', \$string;

I'm in a hurry, so I did not test and I used a hash because implementing FETCHSIZE, STORESIZE, EXTEND, PUSH, POP, SHIFT, UNSHIFT and SPLICE is too much work :)

And there's no error checking.

Hmmm... maybe I should just have said 'Why not tie?'...

- Yes, I reinvent wheels.
- Spam: Visit eurotraQ.

Replies are listed 'Best First'.
Re: Are strings lists of characters?
by Dominus (Parson) on Oct 18, 2002 at 18:10 UTC
    Says juerd:
    sub DELETE { my ($self, $key) = @_: $self->STORE($key, ''); }
    That, unfortunately, doesn't work well. Suppose %h is tied to the string converted, and then you do delete @h{2,5}. You'd like to delete the n and the r, yielding coveted, but that's not what happens. Instead, Perl calls DELETE(2), which deletes the n, leaving coverted, and then DELETE(5), which deletes the t, not the r, leaving covered instead of coveted.

    Of course, that's not your fault, but at present it can't really be made to work right. I was going to put in a patch to fix this (motivated by the same problem using delete with Tie::File) but I haven't gotten around to it yet. The easy solution is that if you're deleting a list of values, Perl should delete them in order from last to first instead of from first to last. That fixes the delete @h{2,5} problem, but unfortunately the same problem persists with delete @h{2,5,3}.

    The patch I planned to make would allow the tied hash class to request that Perl call a special DELETESLICE method instead of making multiple calls to DELETE in such cases. It would follow the same form as the NEGATIVE_INDICES feature in the current bleadperl.

    --
    Mark Dominus
    Perl Paraphernalia
Re: Re: Are strings lists of characters?
by Thelonius (Priest) on Oct 29, 2002 at 20:58 UTC
    package StringArray; require Tie::Array; use base 'Tie::Array'; sub TIEARRAY { bless $_[1], $_[0] } sub FETCH { substr(${$_[0]}, $_[1], 1) } sub STORE { substr(${$_[0]}, $_[1], 1) = $_[2] } sub FETCHSIZE { length(${$_[0]}) } sub STORESIZE { $$self = substr(${$_[0]}, 0, $_[1]) } sub DELETE { substr(${$_[0]}, $_[1], 1) = '' } 1;
    Example:
    #!perl -w use StringArray; use strict; my $test = "Hello dolly"; my @testa; tie @testa, 'StringArray', \$test; print "\$#testa = $#testa\n"; print "testa[1] = $testa[1]\n"; $testa[1] = 'b'; print "testa[1] = $testa[1]\n"; map {$_ = uc $_} @testa; print "after map: test = $test\n"; delete $testa[1]; print "after delete: test = $test\n"; push @testa, "C"; print "after push: test = $test\n";
      Nope - still the same problem.
      #!/usr/bin/perl -w use strict; $_ = "converted"; tie my @test, 'StringArray', $_; print map "$_\n", map { delete @$_[2,5]; join '', grep defined, @$_; } \@test, [ /(.)/sg ]; package StringArray; require Tie::Array; use base 'Tie::Array'; sub TIEARRAY { my $str = pop; bless \$str, shift } sub FETCH { substr(${$_[0]}, $_[1], 1) } sub STORE { substr(${$_[0]}, $_[1], 1) = $_[2] } sub FETCHSIZE { length(${$_[0]}) } sub STORESIZE { $$_[0] = substr(${$_[0]}, 0, $_[1]) } sub DELETE { substr(${$_[0]}, $_[1], 1) = '' } 1; __END__ covered coveted

      Makeshifts last the longest.