Newsgroup: it.comp.lang.perl
Titolo: metavariabile version 2

Supponiamo di avere dei vettori @pippo, @pluto e @paperino e una
serie di file fileXX, che hanno righe del tipo "pippo: 3", "paperino: 7",
"minnie: 6"
Il mio scopo e` aprire uno per uno i fileXX, e se ad esempio il file numero
0 contiene la riga "paperino: 123" allora $paperino[0] = 123.
La mia idea sarebbe avere un array @vars = qw(pippo paperino pluto), 
fare un loop
# $i e` l'indice del file che sto aprendo
while (<FILE>) {
   ($key, $val) = split (/:/);
   foreach $var (@vars) {
      if ($key eq $var) {
	 chomp $val;
e qui mi fermo. Pensavo che 
	${$var}[$i] = $val; 
fosse la soluzione, ma ho scoperto che cio` non e` vero. Suggerimenti vari
e _Programming Perl_ mi hanno fatto scoprire che invece
	eval "\${$var}[$i] = $val"
funziona.
Visto che io non ci ho mai capito un tubo ne` di reference ne` di eval,
qualcuno mi spiega cosa sono riuscito a combinare?
ciao, .mau.

 funziona.
Dunque, considera questo frammento di codice, derivato dal tuo:
 
 my @minni = ();
 my $str= "minni:123";
 my ($key, $val) = split (/:/, $str);     
 
 if( $key eq 'minni' )
 {
	 ${$key}[0] =  $val;
 }
 print $minni[0],"\n";
Questo stampa effettivamente "123", quindi fa quello che tu volevi. Non mi
è chiarissimo, perciò, perchè quella che consideravi la soluzione, in
realtà non lo fosse.
Se sostituisci il codice all'interno dell'if, con 
  eval " \${$key}[0] =  $val ";
ottieni apparentemente il medesimo effetto, ma quello che accade è
qualcosa di profondamente diverso.
La prima versione sfrutta la possibilita di usare una stringa come
riferimento a una variabile. Questo tipo di riferimento è detto simbolico.
Nel nostro caso sarebbe equivalente a scrivere:  ${"minni"}[0]. Nota che
questo codice non viene nemmeno compilato se vige "use strict", o anche
"use strict refs", giacchè in questi casi l'uso di riferimenti simbolici
non viene consentito.
Nella seconda versione, il codice che viene effettivamente consegnato
all'eval (in virtù dell'interpolazione delle variabili) è di fatto
  ${minni}[0] = 123
che è equivalente a  
 $minni[0] = 123  
Questo non fa uso di riferimenti simbolici e compila anche sotto "strict
refs".
Io personalmente non amo nè il ricorso ad eval nè l'impiego di riferimenti
simbolici, e propenderei per un approccio di questo tipo:
 use strict ;
 my @minni = ();
  my %var_ref = 
 (
  	'minni' => \@minni
  );
 my $str= "minni:123";
 my ($key, $val) = split (/:/, $str);     
 if( $key eq 'minni' )
 {
     $var_ref{$key}->[0] = $val;
 }
 print $minni[0],"\n";
 
Max 
 
 
 

Max M. scripsit:
: Dunque, considera questo frammento di codice, derivato dal tuo:
Allora il mio esempio l'ho scritto male :-)
Il programmino qui sotto mi da` come risultato "5 ... 11":
=-=-=-=-=-=-=-=
#!/bin/perl
my @a = qw(pippo pluto paperino);
my (@pippo, @pluto, @paperino) ;
my $var = $a[1];
$pluto[2] = 5;
${$var}[2] = 8;
print "$pluto[2] ... ";
eval "\${$var}[2] =11";
print "$pluto[2]  \n";
=-=-=-=-=-=-=
e quindi e` chiaro che le due assegnazioni fanno qualcosa di diverso
(non so cosa, appunto)
: Io personalmente non amo nè il ricorso ad eval nè l'impiego di riferimenti
: simbolici, e propenderei per un approccio di questo tipo:
[...]
occhei, questo mi funziona (con un if (exists($var_ref{$key})) per testare
una qualunque delle variabili... altrimenti che gusto c'era a fare tutto?)
ed e` anche piu` comprensibile.
grazie e ciao, .mau.

 una qualunque delle variabili... altrimenti che gusto c'era a fare tutto?)
Certo. Puoi anche fare cosě:
 my $ref;
 if( $ref = $var_ref{$key} ) { $ref->[0] = $val }
Max

Max M. scripsit:
: Il punto è che i riferimenti simbolici funzionano soltanto con variabili
: cha hanno un entry in una symbol table. Se estrai @pluto dalla
: dichiarazione 'my' vedrai che anche il tuo funziona.
Non viene fatta una symbol table anche per le variabili di scopo locale? 
in fin dei conti, se queste sono accettate nelle subroutine, dovrebbero
essere scritte da qualche parte.
ciao, .mau.

 essere scritte da qualche parte.
Nella "scratchpad", credo, ma non sono un esperto. Maggiori dettagli in
"perlguts".
Max