OVH Cloud OVH Cloud

bizarre: passage de tableaux en arguments

5 réponses
Avatar
julien
Bonjour
Dans mon programme, lorsque je passe un tableau en arguments à des
sous-porgrammes, le tableau se réduit à son premier élément!

Par exemple:
(...)
print @{$config{$lang}}."\n\n"; #contient 20 éléments
my $value = language($1,$row[1],@{$config{$lang}});

sub language {
my $lang = shift;
my $html = shift;
my @conf = shift;

(...)
print @parse."\n"; #contient 297 éléments
print @conf."\n\n"; #contient 1 élément

my $value=compile(@parse,@conf);
}

sub compile { #donner la valeur pour la langue correspondante
my @parse=shift;
my @conf=shift;
my @values;

print @parse."\n"; #contient 1 élément
print @conf."\n"; #contient 1 élement
}

Les tableaux passent ainsi de 20 à 1 éléments, et de 297 à 1 sans qu'ils
soient modifiés avant le passage en argument! Je ne vois pas à quoi cela
peut être dû.

Julien

5 réponses

Avatar
Rue des Prairies
julien wrote:
Bonjour


Bonjour,

Dans mon programme, lorsque je passe un tableau en arguments à des
sous-porgrammes, le tableau se réduit à son premier élément!

Par exemple:
(...)
print @{$config{$lang}}."nn"; #contient 20 éléments
my $value = language($1,$row[1],@{$config{$lang}});

sub language {
my $lang = shift;
my $html = shift;
my @conf = shift;


shift renvoie le premier élément du tableau en paramètre, @_ par défaut.
pour récupérer le tableau en entier il faut faire :
my @conf = @_;


(...)
print @parse."n"; #contient 297 éléments
print @conf."nn"; #contient 1 élément

my $value=compile(@parse,@conf);
}

sub compile { #donner la valeur pour la langue correspondante
my @parse=shift;
my @conf=shift;
my @values;


Ici il faut passer les tableaux par référence :

my $value = compile(@parse,@conf);

sub compile {
my $ref_parse = shift;
my $ref_conf = shift

Olivier

Avatar
Michel Rodriguez
julien wrote:

Bonjour
Dans mon programme, lorsque je passe un tableau en arguments à des
sous-porgrammes, le tableau se réduit à son premier élément!

Par exemple:
(...)
print @{$config{$lang}}."nn"; #contient 20 éléments
my $value = language($1,$row[1],@{$config{$lang}});

sub language {
my $lang = shift;
my $html = shift;
my @conf = shift;


Dans ce cas il te faut ecrire

@conf= @_; # conf est juste le reste de la liste des parametres

ou

my $value = language($1,$row[1],$config{$lang}); # pas de @{}
...

my $conf= shift; # $conf est une reference a un tableau
print @$conf; # le tableau entier
print $conf->[0]; # 1 element

Ce qui se passe: quand tu appelles language tu lui passes en fait une seule
liste d'arguments. Si @{$config{$lang}} contient ( 'toto', 'tata'), alors
ton appel se comporte (quasiment) comme language($1,$row[1], 'toto',
'tata'); Le fait que toto et tata etaient dans un tableau est perdu. donc
quand tu ecris my @conf = shift; le shift te renvoie juste le prmier
element de la liste.

les 2 solutions que je te propose plus haut sont: recupere toute la liste
dans @conf, elle est dans @_, ou passe une reference a @conf, et travaille
avec cette reference.

Attention, le comportement du code sera different dans les 2 cas: si tu
ecrits @conf=@_; alors tu as une copie du tableau, donc tu ne peux pas
changer le tableau d'origine, alors que si tu passes une reference, tu
travailles avec ce tableau d'origine, et tu peus le modifier. Passer une
reference peut aussi etre plus rapide si le tableau est gros.




__
Michel Rodriguez
Perl & XML
http://xmltwig.com

Avatar
Alex Marandon
In article <3f615111$0$28904$, julien wrote:
Bonjour
Dans mon programme, lorsque je passe un tableau en arguments à des
sous-porgrammes, le tableau se réduit à son premier élément!

Par exemple:
(...)
print @{$config{$lang}}."nn"; #contient 20 éléments
my $value = language($1,$row[1],@{$config{$lang}});

sub language {
my $lang = shift;
my $html = shift;
my @conf = shift;

(...)
print @parse."n"; #contient 297 éléments
print @conf."nn"; #contient 1 élément

my $value=compile(@parse,@conf);
}

sub compile { #donner la valeur pour la langue correspondante
my @parse=shift;
my @conf=shift;
my @values;

print @parse."n"; #contient 1 élément
print @conf."n"; #contient 1 élement
}


Bien sûr, les arguments d'une sub perl sont un tableau. Tous les
éléments sont passés, mais toi tu ne récupère que le premier dans ta sub.
Si tu fais un autres shift(), tuverras que tu récupèreras le second,
etc.

Dans language() pour récupérer tout @conf, le plus simple est de faire
my @conf = @_;

Dans compile(), tu utiliser une référence, au moins pour le premier
argument, de cette façon :
# appel :
my $value=compile(@parse,@conf);
# récupération :
my ($parse_ref, $conf_ref) = @_;
my @parse = @$parse_ref;
my @conf = @$conf_ref;

Avatar
dominique
Michel Rodriguez wrote:
Attention, le comportement du code sera different dans les 2 cas: si tu
ecrits @conf=@_; alors tu as une copie du tableau, donc tu ne peux pas
changer le tableau d'origine, alors que si tu passes une reference, tu
travailles avec ce tableau d'origine, et tu peus le modifier. Passer une
reference peut aussi etre plus rapide si le tableau est gros.



100% d'accord avec cette remarque,
je pense que dans tous les cas il est preferable de passer en parametre
une reference. Ca evitera des allocations memoires pour rien et donc une
perte de temps inutile. Sauf si biensur tu as besoin de travailler sur
une copie pour ne pas modifier le tableau original.

--
Dom

Avatar
julien
julien wrote:
Bonjour
Dans mon programme, lorsque je passe un tableau en arguments à des
sous-porgrammes, le tableau se réduit à son premier élément!
Merci à tous


Julien