Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

questions sur les références

7 réponses
Avatar
mpg
Bonjour,

Je commence à essayer d'utiliser des structures complexes en Perl, et je
voudrais confirmation d'un ou deux points sur les références. Si on a une
liste @liste et qu'on fait :

$a = [@liste];
$b = \@liste;

j'ai l'impression que du coup $a sera une référence à une copie anonyme de
@liste, alors que $b sera une référence à @liste elle-même : en
particulier, si on change $liste[0], ça va changer $b->[0] mais pas
$a->[0]. Ce dernier point est confirmé par l'expérience mais je voudrais
savoir si mon raisonnement est correct.

Maintenant, je ne comprends plus ce qui se passe quand on fait :

sub truc {
my @ls = ('a', 'b');
return \@ls;
}
$c = &truc();
print ("$c->[0]\n");

D'après mon raisonnement précédent, $c contient une référence à @ls tel que
définie dans &truc. Or @ls est locale à truc, donc les valeurs qui lui ont
été attribuées dans truc ne devraient pas être visible depuis l'extérieur ?

Je comprendrais que $c->[0] soit autre chose que undef si on avait terminé
truc par return [@ls], mais là je suis un peu perdu.

Merci d'avance pour vos explications.

Manuel.

7 réponses

Avatar
Nicolas George
mpg wrote in message <gaj2i0$14tr$:
j'ai l'impression que du coup $a sera une référence à une copie anonyme de
@liste, alors que $b sera une référence à @liste elle-même : en
particulier, si on change $liste[0], ça va changer $b->[0] mais pas
$a->[0]. Ce dernier point est confirmé par l'expérience mais je voudrais
savoir si mon raisonnement est correct.



Oui, c'est ça.

sub truc {
my @ls = ('a', 'b');
return @ls;
}
$c = &truc();
print ("$c->[0]n");

D'après mon raisonnement précédent, $c contient une référence à @ls tel que
définie dans &truc. Or @ls est locale à truc, donc les valeurs qui lui ont
été attribuées dans truc ne devraient pas être visible depuis l'extérieur ?

Je comprendrais que $c->[0] soit autre chose que undef si on avait terminé
truc par return [@ls], mais là je suis un peu perdu.



Si tu écris :

my $a = [ 1, 2, 3 ];
my $b = $a;

tu te retrouves avec deux références sur le même objet. Les accès faits à
travers $a ou $b sont absolument, il n'y a rien qui permette de dire que $a
est le vrai et $b le faux.

L'objet en mémoire, [ 1, 2, 3 ], a été créé au moment de définir $a, mais il
continue à exister après la disparition de $a. D'un point de vue théorique,
il existe quelque part en mémoire pour l'éternité à partir du moment où il
est créé. En pratique, l'interpréteur se permet de le supprimer dès qu'il se
rend compte qu'il n'est plus possible de l'atteindre, parce que ça revient
au même.

Si tu écris la même chose en C, ça donne :

int *a = malloc(3 * sizeof(int));
int *b = a;

Maintenant, le cas avec une liste. En C, tu aurais écrit :

int a[3] = { 1, 2, 3 };
int *b = a;

Et là, tu aurais eu raison : dès qu'on sort de la portée de a, on n'a plus
le droit de déréférencer b.

Mais en perl, toutes les allocations sont dynamiques :

my @a = ( 1, 2, 3 );
my $b = @a;

diffère de la première version uniquement en ce qu'on peut (et doit) écrire
« $a[42] » et pas « $a->[42] », etc. Le principe reste le même : @a et @$b
sont deux accès au même objet qui continue à exister moralement pour
l'éternité.
Avatar
Paul Gaborit
À (at) Sun, 14 Sep 2008 15:11:26 +0200,
mpg écrivait (wrote):
Je commence à essayer d'utiliser des structures complexes en Perl, et je
voudrais confirmation d'un ou deux points sur les références. Si on a une
liste @liste et qu'on fait :

$a = [@liste];
$b = @liste;

j'ai l'impression que du coup $a sera une référence à une copie anonyme de
@liste, alors que $b sera une référence à @liste elle-même : en
particulier, si on change $liste[0], ça va changer $b->[0] mais pas
$a->[0]. Ce dernier point est confirmé par l'expérience mais je voudrais
savoir si mon raisonnement est correct.



Oui, vous avez très bien compris.

Maintenant, je ne comprends plus ce qui se passe quand on fait :

sub truc {
my @ls = ('a', 'b');
return @ls;
}
$c = &truc();
print ("$c->[0]n");

D'après mon raisonnement précédent, $c contient une référence à @ls tel que
définie dans &truc. Or @ls est locale à truc, donc les valeurs qui lui ont
été attribuées dans truc ne devraient pas être visible depuis l'extérieur ?

Je comprendrais que $c->[0] soit autre chose que undef si on avait terminé
truc par return [@ls], mais là je suis un peu perdu.



'my @ls' ne signifie pas que le tableau n'est visible que dans 'truc'.
Ce qui n'est visible que dans 'truc', c'est le *nom* 'ls'.

Pour les valeurs (scalaires, tableaux, tables de hachage), Perl les
conservent en mémoire tant qu'il existe au moins une référence
pointant vers elles. Ici, c'est $c qui conserve cette référence. Les
valeurs continuent donc à exister (heureusement d'ailleurs car c'est
bien pratique).

Cela explique aussi pourquoi, en cas de référencement circulaire, il
faut casser le cycle soi-même (dans les versions actuelles de perl).

PS: n'utilisez pas la notation '&truc()' pour appeler une fonction :
ça empêche l'utilisation d'un éventuel prototype. Utilisez plus
simplement 'truc()'. Pour mieux comprendre, lisez perlsub.

--
Paul Gaborit - <http://perso.enstimac.fr/~gaborit/>
Perl en français - <http://perl.enstimac.fr/>
Avatar
Paul Gaborit
À (at) Sun, 14 Sep 2008 16:43:31 +0200,
Paul Gaborit écrivait (wrote):
À (at) Sun, 14 Sep 2008 15:11:26 +0200,
mpg écrivait (wrote):
Je commence à essayer d'utiliser des structures complexes en Perl, et je




[...]

Oui, vous avez très bien compris.



Désolé pour le vouvoiement, je n'avais pas vu/lu que c'était toi...
Mais ça ne change en rien le fond de ma réponse ! ;-)

--
Paul Gaborit - <http://perso.enstimac.fr/~gaborit/>
Perl en français - <http://perl.enstimac.fr/>
Avatar
mpg
Le (on) dimanche 14 septembre 2008 16:43, Paul Gaborit a écrit (wrote) :

j'ai l'impression que du coup $a sera une référence à une copie anonyme
de @liste, alors que $b sera une référence à @liste elle-même : en
particulier, si on change $liste[0], ça va changer $b->[0] mais pas
$a->[0]. Ce dernier point est confirmé par l'expérience mais je voudrais
savoir si mon raisonnement est correct.



Oui, vous avez très bien compris.



Oki.

'my @ls' ne signifie pas que le tableau n'est visible que dans 'truc'.
Ce qui n'est visible que dans 'truc', c'est le *nom* 'ls'.



Vu, merci pour vos explications à tous les deux. Le point est donc qu'en
Perl les valeurs sont globales (moralement éternelles), mais pas les noms.
Ce qui donne l'illusion d'avoir des variables locales, c'est que si un nom
était la seule référence à une valeur et que ce nom disparait, la valeur
disparaîtra aussi.

Du coup ce qui est moins clair pour moi, c'est à quel moment Perl décide de
créer des nouvelles valeurs. Par exemple :

my $truc;

force Perl à créer une nouvelle valeur et à faire de $truc un nom local pour
cette valeur, c'est ça ? Et sinon à chaque fois qu'on fait une assignation
du style

$a = $b;
$a = "valeur";

une nouvelle valeur est crée (éventuellement comme copie) ?

PS: n'utilisez pas la notation '&truc()' pour appeler une fonction :
ça empêche l'utilisation d'un éventuel prototype. Utilisez plus
simplement 'truc()'. Pour mieux comprendre, lisez perlsub.



Vu que je ne sais pas (encore) ce qu'est un prototype (une notion d'orienté
objet, j'imagine), je vais plutôt te croire sur parole pour le moment :-)

Manuel.
Avatar
mpg
Le (on) dimanche 14 septembre 2008 17:06, Paul Gaborit a écrit (wrote) :


À (at) Sun, 14 Sep 2008 16:43:31 +0200,
Paul Gaborit écrivait (wrote):
À (at) Sun, 14 Sep 2008 15:11:26 +0200,
mpg écrivait (wrote):
Je commence à essayer d'utiliser des structures complexes en Perl, et je




[...]

Oui, vous avez très bien compris.



Désolé pour le vouvoiement, je n'avais pas vu/lu que c'était toi...
Mais ça ne change en rien le fond de ma réponse ! ;-)



J'ai effectivement hésité à te faire remarquer que sur fctt on se
tutoyait :-) Pour le fond, ça vient progressivement, mais je serai moins
souvent tenté de proclamer que Perl est un langage simple...

Manuel.
Avatar
Paul Gaborit
À (at) Sun, 14 Sep 2008 18:08:56 +0200,
mpg écrivait (wrote):
J'ai effectivement hésité à te faire remarquer que sur fctt on se
tutoyait :-) Pour le fond, ça vient progressivement, mais je serai moins
souvent tenté de proclamer que Perl est un langage simple...



Il n'est pas simple. Il a juste une courbe d'apprentissage linéaire...
et très longue car on peut toujours en apprendre plus ! ;-)

--
Paul Gaborit - <http://perso.enstimac.fr/~gaborit/>
Perl en français - <http://perl.enstimac.fr/>
Avatar
Paul Gaborit
À (at) Sun, 14 Sep 2008 17:26:03 +0200,
mpg écrivait (wrote):
Du coup ce qui est moins clair pour moi, c'est à quel moment Perl décide de
créer des nouvelles valeurs. Par exemple :

my $truc;

force Perl à créer une nouvelle valeur et à faire de $truc un nom local pour
cette valeur, c'est ça ? Et sinon à chaque fois qu'on fait une assignation
du style



En fait, on peut dire que 'my $truc' a deux effets :

1- créer une nouvelle variable scalaire.

2- associer le nom '$truc' à cette variable mais uniquement dans la
portée du 'my'.

$a = $b;
$a = "valeur";

une nouvelle valeur est crée (éventuellement comme copie) ?



Si c'est la première apparition de '$a', la première ligne crée
effectivement une nouvelle variable scalaire et y copie la valeur de
$b. Lors de la deuxième affectation, seule la valeur de $a change. La
variable exsitait déjà.

(Une petite nuance : $a et $b sont des variables qui existent toujours
car elles sont utilisées dans les fonctions de tris pour nommer les
dexu valeurs à comparer.)

PS: n'utilisez pas la notation '&truc()' pour appeler une fonction :
ça empêche l'utilisation d'un éventuel prototype. Utilisez plus
simplement 'truc()'. Pour mieux comprendre, lisez perlsub.



Vu que je ne sais pas (encore) ce qu'est un prototype (une notion d'orienté
objet, j'imagine), je vais plutôt te croire sur parole pour le moment :-)



Un prototype sert juste à préciser le type (au sens Perl) des
paramètres d'une fonction. Ce n'est pas utile dans un premier temps,
d'autant que ça peut "enduire d'erreur".

--
Paul Gaborit - <http://perso.enstimac.fr/~gaborit/>
Perl en français - <http://perl.enstimac.fr/>