Schrift
[thread]7635[/thread]

Übergabe einer sort-Funktion an eine Methode: Problem beim Zugriff auf $a und $b



<< |< 1 2 3 >| >> 24 Einträge, 3 Seiten
docsnyder
 2006-01-19 11:16
#62049 #62049
User since
2005-09-08
300 Artikel
BenutzerIn
[Homepage] [default_avatar]
Hallo!

Ich habe folgendes Problem mit dem Aufruf einer eigenen Sort-Funktion an eine Methode einer Klasse.

Um zu verdeutlichen, worum es genau geht, hier zunächst ein Beispiel zur Vorgehensweise "ohne" daß eine Klasse im Spiel ist:

Code: (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
sub myCmp {
$a cmp $b;
}

sub myFunc {
my($sortFunc, @arr) = @_;

# do something ...

@arr = sort $sortFunc @arr;

# do something else ...

return(@arr);
}

@tmpArr = ( "xxx", "aaa", "zzz", "bbb" );
@tmpArr = myFunc(\&myCmp, @tmpArr);


Wenn ich nun myFunc() zu einer Methode einer Klasse mache (sagen wir myMethod()), und wenn die zu vergleichenden Werte $a und $b jetzt Objekte (mit einer Methode name()) sind (übergeben wird an sort() ein Array mit Objekten), scheint das nicht mehr zu funktionieren:

Code: (dl )
1
2
3
4
5
6
7
sub myCmp {
$a->name() cmp $b->name();
}

@tmpArr = ( $obj_1, $obj_2, $obj_3 );

$someObj->myMethod(\&myCmp, @tmpArr);


Wird jetzt in myMethod() die Sort-Funktion myCmp() aufgerufen und das Array übergeben, kann die Methode name() nicht mehr für $a bzw. $b aufgerufen werden. Ich bekomme den Fehler

Code: (dl )
Can't call method "name" on an undefined value at ./usTree.pl line ...


Und in der Tat, wenn ich myCmp() wie folgt definiere:

sub myCmp {
print("comparing '$a' and '$b' ...\n");
$a cmp $b;
}

bekomme ich die folgende Ausgabe:

Code: (dl )
comparing '' and '' ...


In myMethod() kann ich für jedes Array-Element, das an sort() übergeben wird, die Methode name() aufrufen und bekomme ein sinnvolles Ergebnis, das Array ist also nicht leer, wie es die Fehlermeldung vermuten läßt.

Was läuft hier falsch?

Gruß, Doc
esskar
 2006-01-19 11:47
#62050 #62050
User since
2003-08-04
7321 Artikel
ModeratorIn

user image
$a und $b ist nur explizit beim direkten sort möglich.
hab es zwar nicht getestet aber ich tippe auf folgendes

Code: (dl )
1
2
3
sub myCmp {
$_[0]->name() cmp $_[1]->name();
}
docsnyder
 2006-01-19 12:12
#62051 #62051
User since
2005-09-08
300 Artikel
BenutzerIn
[Homepage] [default_avatar]
@esskar

Klingt gut, aber wenn ich statt $a und $b $_[0] und $_[1] verwende, bekomme ich folgenden Fehler:

Code: (dl )
Can't call method "name" on unblessed reference at ./usTree.pl line 83.


Hhhmmmmm!

Any Idea?

Gruß, Doc
esskar
 2006-01-19 12:20
#62052 #62052
User since
2003-08-04
7321 Artikel
ModeratorIn

user image
teste das mal
Code: (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#!/usr/bin/perl

use strict;
use warnings;

my @array = 1..100;

sub backward { $b <=> $a }

mysort(\&backward);

sub mysort {
my $func = shift;

print join("\n", sort $func @array);
}
Dubu
 2006-01-19 12:22
#62053 #62053
User since
2003-08-04
2145 Artikel
ModeratorIn + EditorIn

user image
[quote=esskar,19.01.2006, 10:47]$a und $b ist nur explizit beim direkten sort möglich.
hab es zwar nicht getestet aber ich tippe auf folgendes

Code: (dl )
1
2
3
sub myCmp {
  $_[0]->name() cmp $_[1]->name();
}
[/quote]
Aber zwingend mit Prototyp (siehe perldoc -f sort):
Code: (dl )
1
2
3
sub myCmp ($$) {
  $_[0]->name() cmp $_[1]->name();
}
docsnyder
 2006-01-19 12:34
#62054 #62054
User since
2005-09-08
300 Artikel
BenutzerIn
[Homepage] [default_avatar]
@esskar

Genauso mache ich das ja und das funzt auch. Es geht eben nicht mehr, wenn die Funktion, an die ich die Sort-Funktion übergebe und die dann sort() aufruft (in Deinem Beispiel mysort()), eine Methode eines Objektes ist. Geht das irgendwas verloren, weil der Name-Space innerhalb und außerhalb der Klasse ein anderer ist?

Gruß, Doc
esskar
 2006-01-19 12:40
#62055 #62055
User since
2003-08-04
7321 Artikel
ModeratorIn

user image
irgendwas machst du falsch

Code: (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#!/usr/bin/perl

use strict;
use warnings;


my @array = map { A->new($_) } 1..100;

sub backward { $b->value <=> $a->value }

mysort(\&backward);

sub mysort {
my $func = shift;

print join("\n", map { $_->value } sort $func @array);
}

package A;

sub new {
my $class = shift;
my $val = shift;

return bless [$val], $class;
}

sub value {
my $class = shift;
return $class->[0];
}

1;
docsnyder
 2006-01-19 12:50
#62056 #62056
User since
2005-09-08
300 Artikel
BenutzerIn
[Homepage] [default_avatar]
@esskar

Yep, Dein Code läuft.

Ich glaube, ich habe das mit dem bless() nicht hinreichend verstanden. Was mache ich falsch:

Code: (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
sub new {
my($class) = shift;
my($name) = shift;
my($self) = {};

$self = { childs => \() };

bless($self, $class);

$self->{name} = $name;
$self->{parent} = undef;

return($self);
}


???

Gruß, Doc
Crian
 2006-01-19 13:30
#62057 #62057
User since
2003-08-04
5866 Artikel
ModeratorIn
[Homepage]
user image
was ist \() ?\n\n

<!--EDIT|Crian|1137670278-->
s--Pevna-;s.([a-z]).chr((ord($1)-84)%26+97).gee; s^([A-Z])^chr((ord($1)-52)%26+65)^gee;print;

use strict; use warnings; Link zu meiner Perlseite
docsnyder
 2006-01-19 13:50
#62058 #62058
User since
2005-09-08
300 Artikel
BenutzerIn
[Homepage] [default_avatar]
\() ist eine Referenz auf eine namenlose Liste.
<< |< 1 2 3 >| >> 24 Einträge, 3 Seiten



View all threads created 2006-01-19 11:16.