[Roma.pm] senza vergogna

Flavio Poletti flavio at polettix.it
Tue Jan 8 14:35:25 PST 2008


(mi scuso per la sciatteria di questa risposta, ma non mi è venuto in
mente niente di più semplice).

Una lista è una cosa differente da un array. Nel caso specifico, puoi
pensare ad un array come ad una lista dotata di una maniglia: se vuoi
prenderla e trasportarla da qualche parte, basta usare la maniglia.

Qual è la maniglia? Sostanzialmente è data dal fatto che a questa lista di
elementi assegni uno spazio ben determinato, che puoi indicare con un nome
o un riferimento. Infatti, puoi creare un array in due modi: o utilizzando
una variabile che comincia con "@":

   @array = 1 .. 10;

oppure utilizzando un costruttore anonimo, che restituisce un riferimento
all'array stesso:

   $rif_ad_array = [ 1 .. 10 ];

Sempre parlando di riferimenti, puoi prendere un riferimento ad "@array"
con il backslash, tipo:

   $rif_ad_altro_array = \@array;

Come vedi, abbiamo modo di "dare un nome" a qualcosa che poi possiamo
portarci appresso ed utilizzare, sia questo il nome dell'array (come
"array" in "@array") o di un riferimento ad esso (come "$rif_ad_array").

Senza la "maniglia" non hai modo di poter dire "sto parlando di questo,
questo e quest'altro elemento": puoi solo far "scivolare" gli elementi
come una sequenza indistinta. Ci sono casi, come la chiamata a funzione,
in cui un array viene "appiattito" in una lista, e da quel punto non ti
rimane altro, tipo in:

   funz(@array1, @array2);

   sub funz {
      my @elementi_in_ingresso = @_;
   }

Qui, in fase di chiamata di "funz()" sia "@array1" che "@array2" vengono
appiattiti e viene creata *una* lista unica, che poi viene passata a
"funz()" stessa. In teoria, sarebbe possibile evitare questo appiattimento
degli array utilizzando i prototipi, ma ci porta un po' fuori obiettivo e
puoi eventualmente approfondirlo da solo sulla documentazione. La cosa
importante, però, è capire che se i prototipi possono evitare
l'appiattimento degli array, se tu *già parti* da una lista non hai modo
di farci niente: rimarrà sempre e solo una lista.

In particolare, quindi, se hai due funzioni che restituiscono liste:

  sub funz1 { return 1 .. 10; }
  sub funz2 { return 20 .. 30; }

metterle come sotto-chiamate ti produrrà solo una lista più lunga:

  funz(funz1(), funz2()); # crea una sola, lunga lista

Se hai bisogno di maniglie, devi passare per gli array. Questo però non ti
obbliga a doverle "nominare", basta che tu aggiunga le maniglie, ad
esempio con il costruttore anonimo di array che abbiamo visto sopra:

  funz([funz1()], [funz2()]);

In questo modo, la lista restituita da "funz1()" viene "catturata" e messa
in un array (anonimo), un riferimento al quale viene passato come primo
parametro a "funz()". Stessa cosa per "funz2()". Quindi, nella sub ti
ritrovi:

   sub funz {
      my ($rif1, $rif2) = @_;
      # qui usi @$rif1 e @$rif2 come da documentazione...
   }

Un'alternativa potrebbe essere quella di restituire riferimenti ad array
invece di liste, tipo:

   sub funz1 { return [ 1 .. 10 ]; } # uso il costruttore anonimo

   sub funz2 {
      my @risultato = 20 .. 30;
      return \@risultato;
   }

   funz(funz1(), funz2()); # già ho dei riferimenti ad array

La scelta sta a te.

Infine, va detto che la sintassi stessa di Perl dà adito, a mio modo di
vedere, a confusione a riguardo. Ad esempio, la funzione "wantarray"
dovrebbe essere chiamata, più logicamente, "wantlist", visto che si può
restituire una lista ma non un array:

   sub ultimafunz {
      my @array = qw( ciao a tutti );
      return @array;
   }

Quest'ultima funzione, ad esempio, restituisce la lista derivante
dall'appiattimento di @array, ma sempre di lista si tratta.

Spero di non aver detto troppe corbellerie, ma per quelle c'è emazep :)

Ciao,

   Flavio.

PS la mail non l'ho riletta, non sparate sul pianista :)


> come dicevo a stefano vorrei essere libero di chiamare la sub usando
> liste o risultati (sempre liste) di altre sub.
>
> non ce' modo di separare le liste senza "nominarle" ?
>
> comuqnue piu'tardi do una scorsa all'indirizzo sui riferimenti.
>
> thx
>
>
>
>> Ciao,
> usa i riferimenti =>> perldoc perlref
>> Praticamente alla funzione gli passi i riferimenti agli array.
>> Successivamente dentro la funzione recuperi il contenuto delle strutture
>> dati passate
>> dereferenziando il riferimento stesso:
>
>> sub non_mischia {
>>     #recuperi i riferimenti passati nella chiamata
>>     my ($ref_list1, $ref_list2) = @_;
>>     #dereferenzi e crei un array come quello passato
>>     my @list1 = @$ref_list1;
>>     #idem con patate
>>     my @list2 = @$ref_list2;
>> }
>
>> #chiami la funzione passando i riferimenti e non gli array
>> non_mischia(\@list1, \@list2);
>
>> Il concetto e' questo, per capire la sintassi e le sfumature, leggiti il
>> manuale.
>
>> Saluti
>
>
>
> --
> Best regards,
>  kanak                            mailto:kanak at perl.it
>
> _______________________________________________
> Roma mailing list
> Roma at pm.org
> http://mail.pm.org/mailman/listinfo/roma
>




More information about the Roma mailing list