zifnab: Rückgabe eines mehrdimensionalen Arrays

Hi,
ich benötige eine Funktion, die mir 2 Arrays zurückgibt.
Da die Reihenfolge der Werte wichtig ist(!), kann ich nicht problemlos mit Hashes arbeiten.
In meiner Lösung habe ich dazu ein Array mit 2 Feldern erzeugt. Jedes seiner Felder enthält den Verweis auf eines der zurückzugebenden Arrays.
Da diese Verweise beim Erzeugen des Rückgabewertes nicht durch perl aufgelöst werden ( keine Dereferenzierung ) sondern im Returnwert enthalten sind, kann ich nur solange auf den Rückgabewert zugreifen, wie die Referenzen auf einen tatsächlich vorhandenen Speicherinhalt zeigen.
Sobald ich also am Ende der Funktion 'unset' auf die 2 Arrays aufrufe, fliegt mir der Rückgabewert um die Ohren.
Kann mir jemand aus der Patsche helfen?

  
sub gib_2_arrays_zurück {  
my @ret_array     = ();  
my @vorname       = ();  
my @nachname      = ();  
  
# vorname und nachname werden gefüllt, dann...  
  
	@ret_array[0] = \@vorname;  
	@ret_array[1] = \@nachname;  
  
	unset( @vorname ); # lässt @ret_array[0] ins nirvana zeigen  
	unset ( @nachname ); # lässt @ret_array[1] ins nirvana zeigen  
  
	return @ret_array;  
}  

  1. Sobald ich also am Ende der Funktion 'unset' auf die 2 Arrays aufrufe, fliegt mir der Rückgabewert um die Ohren.

    Warum machst du das überhaupt? Perl kümmert sich um die speicherverwaltung, da brauchst gar nicht einzugreifen.

    Aber ich frge mich, warum du nicht einfach die zwei Arrays als Referenzen zurück gibst?

      
     sub gib_2_arrays_zurück {  
     my @vorname       = ();  
     my @nachname      = ();  
      
     return (\@vorname, \@nachname);  
    }  
    
    

    Struppi.

    1. Sobald ich also am Ende der Funktion 'unset' auf die 2 Arrays aufrufe, fliegt mir der Rückgabewert um die Ohren.

      Warum machst du das überhaupt? Perl kümmert sich um die speicherverwaltung, da brauchst gar nicht einzugreifen.

      Das selbe Problem hätte ich, wenn ich @vorname mit neuen Werten belege, aber im 2-dim Array die alten Werte haben möchte.

      Aber ich frge mich, warum du nicht einfach die zwei Arrays als Referenzen zurück gibst?

      Ich fürchte, weil ich zu dumm bin, die Rückgabewerte sauber zuzuweisen :-(

      sub gib_2_arrays_zurück {
      my @vorname       = ();
      my @nachname      = ();

      return (@vorname, @nachname);
      }

      
      >   
      >   
      > Struppi.
      
  2. Sobald ich also am Ende der Funktion 'unset' auf die 2 Arrays aufrufe, fliegt mir der Rückgabewert um die Ohren.

    Jetzt verstehe ich. Die Funktion unset ist von dir (ich dachte schon ich hätte mal wieder ein neues Perl Feature verpaßt). Dann frag ich mich aber wirklich warum du etwas löscht, was du später verwenden willst?

    Auch wenn ich es für umständlich und performancefeindlich halte ein Array unnötig zu kopieren, du kannst natürlich auch Referenzen dereferenzieren, das sieht aber extrem unschön aus.

    sub x{  
    my @a = qw(1 2 3 4);  
    my @b = qw(4 3 2 1);  
      
    my @ret = ([@{\@a}], [@{\@b}]);  
      
    @a = ();  
    @b = ();  
      
    return \@ret;  
    }  
      
    use Data::Dumper;  
      
    print Dumper x();  
    
    

    Struppi.

    1. Auch wenn ich es für umständlich und performancefeindlich halte ein Array unnötig zu kopieren, du kannst natürlich auch Referenzen dereferenzieren, das sieht aber extrem unschön aus.

      Er kann natürlich Referenzen der Arrays an die zu behandelnde Funktion übergeben. Dann ist sein caller der Eigentümer der Referenzen.

      my $aref=[];  
      somefunc($aref);  
        
      sub somefunc{  
        my $aref=shift;  
        #arbeite mit der übergebenen Referenz  
        return 1;  
        #im Erfolgsfall, damit der Caller auch logisch operiert.  
      }  
      
      

      mfg Beat

      --
      ><o(((°>           ><o(((°>
         <°)))o><                     ><o(((°>o
      Der Valigator leibt diese Fische
      1. Auch wenn ich es für umständlich und performancefeindlich halte ein Array unnötig zu kopieren, du kannst natürlich auch Referenzen dereferenzieren, das sieht aber extrem unschön aus.

        Er kann natürlich Referenzen der Arrays an die zu behandelnde Funktion übergeben. Dann ist sein caller der Eigentümer der Referenzen.

        Inwiefern sollte das helfen?

        Struppi.

        1. Auch wenn ich es für umständlich und performancefeindlich halte ein Array unnötig zu kopieren, du kannst natürlich auch Referenzen dereferenzieren, das sieht aber extrem unschön aus.

          Er kann natürlich Referenzen der Arrays an die zu behandelnde Funktion übergeben. Dann ist sein caller der Eigentümer der Referenzen.

          Inwiefern sollte das helfen?

          Meine Ahnung sagt mir, dass er diese erzeugten Arrays zur richtigen Zeit zurücksetzen möchte, was er aber nur kann, wenn er den Zeitpunkt kontrolliert.

          mfg Beat

          --
          ><o(((°>           ><o(((°>
             <°)))o><                     ><o(((°>o
          Der Valigator leibt diese Fische
    2. Sobald ich also am Ende der Funktion 'unset' auf die 2 Arrays aufrufe, fliegt mir der Rückgabewert um die Ohren.

      Jetzt verstehe ich. Die Funktion unset ist von dir (ich dachte schon ich hätte mal wieder ein neues Perl Feature verpaßt). Dann frag ich mich aber wirklich warum du etwas löscht, was du später verwenden willst?

      Auch wenn ich es für umständlich und performancefeindlich halte ein Array unnötig zu kopieren, du kannst natürlich auch Referenzen dereferenzieren, das sieht aber extrem unschön aus.

      sub x{

      my @a = qw(1 2 3 4);
      my @b = qw(4 3 2 1);

      my @ret = ([@{@a}], [@{@b}]);

      @a = ();
      @b = ();

      return @ret;
      }

      use Data::Dumper;

      print Dumper x();

      
      >   
      >   
      >   
      > Struppi.  
      
      Hi,  
      in irgendeinem schlauen Forum habe ich die Empfehlung unset() zu verwenden aufgeschnappt. Das ist keine Funktion von mir ( und laut Perl-Doku auch keine von Perl ;-) ) trotzdem scheint sie zu existieren und tatsächlich die Arrays wieder zu leeren.  
      Nach eurem Feedback habe ich sie aber nun asu dem Code entfernt.  
        
      Tatsächlich war "my @ret = ([@{\@a}], [@{\@b}]);" das, was ich wollte.  
        
      Ich versuche mit:  
      ~~~perl
        
      .  
      .  
      return ( \@vornamen, \@nachnamen );  
        
      my ( @vornamen, @nachnamen ) = gib_mir_2_zurueck  
      
      

      die beiden Rückgabewerte entgegen zu nehmen und gleichzeitg die Referenzen wieder zu dereferenzieren.
      Offensichtlich ist das falsch. Ich vermute er packt mir beide Arrays in eins und speichert das in @vornamen?!
      Trotz wilder Suche in den weiten des Web habe ich kein Beispiel für eine Lösung gefunden.

      1. in irgendeinem schlauen Forum habe ich die Empfehlung unset() zu verwenden aufgeschnappt. Das ist keine Funktion von mir ( und laut Perl-Doku auch keine von Perl ;-) ) trotzdem scheint sie zu existieren und tatsächlich die Arrays wieder zu leeren.
        Nach eurem Feedback habe ich sie aber nun asu dem Code entfernt.

        Tatsächlich war "my @ret = ([@{@a}], [@{@b}]);" das, was ich wollte.

        Ich versuche mit:

        .
        .
        return ( @vornamen, @nachnamen );

        my ( @vornamen, @nachnamen ) = gib_mir_2_zurueck

        
        > die beiden Rückgabewerte entgegen zu nehmen und gleichzeitg die Referenzen wieder zu dereferenzieren.  
        > Offensichtlich ist das falsch. Ich vermute er packt mir beide Arrays in eins und speichert das in @vornamen?!  
        > Trotz wilder Suche in den weiten des Web habe ich kein Beispiel für eine Lösung gefunden.  
          
        Du solltest schlicht die grundlegenden Dokumentationen lesen.  
        Perl übergibt an Subfunktionen schlicht Listen. Ein return übergibt ebenfalls eine Liste. Wenn du nicht weisst, was eine Liste ist, hast du ein Problem. Ein Array speichert zum Beispiel eine Liste von Arrayelementen.  
          
        @arr=func();  
        wird immer die gesammte Liste aufnehmen. Wenn du das nicht willst:  
        ( $elem1, $elem2, @rest ) = func();  
        elem1 und elem2 sind Scalare und können nur je ein Element aus der Liste aufnehmen.  
          
        mfg Beat
        
        -- 
        
        ><o(((°>           ><o(((°>  
        
           <°)))o><                     ><o(((°>o  
        Der Valigator leibt diese Fische
        
  3. Hi,

    ich benötige eine Funktion, die mir 2 Arrays zurückgibt.
    Da die Reihenfolge der Werte wichtig ist(!), kann ich nicht problemlos mit Hashes arbeiten.

    Kannse doch ;)
    Damit ist es möglich, den anonymen Arrays Namen zu verpassen, damit wird der Code später übersichtlicher:

      
    sub foo{  
      my @a; # Namen hier drin  
      my @b; # Vornamen hier drin  
      # Return a hash-ref  
      return {names => \@a, firstnames => \@b};  
    }  
    
    

    Sobald ich also am Ende der Funktion 'unset' auf die 2 Arrays aufrufe, fliegt mir der Rückgabewert um die Ohren.

    Siehe Antwort Struppi. Obenstehende sub foo{} legt Referenzen an, die später noch gebraucht werden, hinzu kommen in der Symboltabelle lediglich die Scalare 'names' und 'firstnames', die auf Speicheradressen zeigen.

    Hotti