Thread Tie::File mit referenziertem Array in package (2 answers)
Opened by sman at 2010-12-09 00:26

MatthiasW
 2010-12-09 16:08
#143438 #143438
User since
2008-01-27
367 Artikel
BenutzerIn
[default_avatar]
Auf den ersten Blick sehe ich "nur" einen Fehler: Bei jeder Instanzierung wird dieselbe Variable an 'Tie::File' gebunden.
Zusätzlich habe ich deinem Beispielcode entnommen, dass du als Beginn der Zeilennummerierung einer Datei eine 1 erwartest; momentan erfolgt der Zugriff auf die 5. Zeile einer Datei über den Index 4, da ein Array zu Grunde liegt und man davon ausgehen kann, dass $[ auf 0 gesetzt ist. (edit3: Ob $[ wohl bei CPAN:Tie::File überhaupt relevant ist? Trotzdem entspricht laut Dokumentation die 1. Zeile der Datei dem Element 0 des Arrays.)

Damit mehrere Instanzen deiner Klasse nebeneinander existieren und funktionieren können, muss die Variable @a in den Konstruktor gezogen werden:
Code (perl): (dl )
1
2
3
sub new {
    ...
    tie \my @a, ...

Darüber hinaus, empfinde ich die get() und set() Methoden als ein wenig zu kompliziert geschrieben, da sich das Arbeiten mit Array-Slices hier anbietet:
Code (perl): (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
sub get {
    my( $self, @pos ) = @_;

    #return @{ $self->{'a'} }[ @pos ];
    return @{ $self->{'a'} }[ map $_-1, @pos ];
}

sub set {
    my( $self, %lines ) = @_;

    my @pos = keys %lines;

    #@{ $self->{'a'} }[ @pos ] = @lines{ @pos };
    @{ $self->{'a'} }[ map $_-1, @pos ] = @lines{ @pos };

    return $self;
}

Um Aufrufketten auch bei Verwendung der set() Methode benutzen zu können, habe ich ihren Rückgabewert auf das aufrufende Objekt ($self) geändert.

Die DESTROY() Methode - und damit auch untie() - wird aufgerufen, sobald das Objekt zerstört wird, also keine Referenz auf das Objekt mehr in Umlauf ist.
Wenn nur eine Objektvariable auf das Objekt referenziert, dann wird DESTROY() aufgerufen, sobald diese Variable aus ihrem Scope läuft, was nach Durchlaufen der gezeigten if-Bedingung der Fall ist. (edit: Das kann man auch ganz einfach testen, indem man in DESTROY() etwas ausgeben lässt und dort versucht dieselbe Datei nochmals nach bzw. vor untie() zu öffnen.)

edit2: Zum Testen ob die Datei geöffnet ist, muss man noch einen Lock einbauen. Im Konstruktor: tied(@a)->flock; im Destruktor:
Code (perl): (dl )
1
2
open my $fh, '<', $self->{'file'} or die "open: $!";
flock(LOCK_EX | LOCK_NB) or die "lock: $!";


MfG
Last edited: 2010-12-09 20:17:47 +0100 (CET)
perl -E'*==*",s;;%ENV=~m,..$,,$&+42;e,$==f;$"++for+ab..an;@"=qw,u t,,print+chr;sub f{split}say"@{=} me"'

View full thread Tie::File mit referenziertem Array in package