SlideShare une entreprise Scribd logo
1  sur  32
Referències & Subrutines
                                        Jordi Delgado
                                    Curs BCN Perl Mongers
                                       5 Novembre 2011
                                 remember, remember the fifth of November...




sábado 12 de noviembre de 2011
Els Array i els Hash poden
                            contenir només escalars...


                  Com podem construir estructures
                        de dades complexes?




sábado 12 de noviembre de 2011
doncs com sempre... amb punters!

                                 referències = punters




sábado 12 de noviembre de 2011
Operador referència: 
                Context escalar: referència
                 Context llista: llista de
                                 referències

                        Una referència és un escalar




sábado 12 de noviembre de 2011
exemples:
     my $nom = ‘anonymous’;
     my $nom_ref = $nom;   # referència a escalar


     my @llista = qw< anon1 anon2 anon3 >;
     my $llista_ref = @llista   # referència a array
     my $aliased_llista = $llista_ref;


     my %diccionari = (
            op1 => ‘fail’,
            op2 => ‘success’,
            op3 => ‘unknown’,
            op4 => ‘unknown’
            );
     my $diccionari_ref = %diccionari; # referència a hash
     my $aliased_diccionari = $diccionari_ref;




sábado 12 de noviembre de 2011
Des-referenciar: afegir un sigil més que
                 dependrà d’allò referenciat,
           utilitzant claus envoltant la referència
     my @llista = qw< anon1 anon2 anon3 >;
     my $llista_ref = @llista    # referència a array
     my $aliased_llista = $llista_ref;
     print "@{ $llista_ref } n";


     my %diccionari = (
            op1 => ‘fail’,
            op2 => ‘success’,
            op3 => ‘unknown’,
            op4 => ‘unknown’
            );
     my $diccionari_ref = %diccionari; # referència a hash
     my $aliased_diccionari = $diccionari_ref;
     print keys %{ $diccionari_ref } , "n";
     print values %{ $diccionari_ref } , "n";




sábado 12 de noviembre de 2011
Però, si el que volem des-referenciar
          és només una variable escalar
            no fan falta les claus {}

                           @{ $llista_ref } = @$llista_ref
                        ${ $llista_ref }[0] = $$llista_ref[0]
               print $$llista_ref[$_], "n" foreach (0..$#$llista_ref)


                 %{ $diccionari_ref } = %$diccionari_ref
          ${ $diccionari_ref }{'op2'} = $$diccionari_ref{'op2'}
     print $$diccionari_ref{$_}, "n" foreach keys %$diccionari_ref;



          farem servir les claus {} només per
                desambiguar, quan calgui


sábado 12 de noviembre de 2011
Ara ja podem construir estructures de
                dades complexes:
     my %ops_from_anon1 = (
             op1 => ‘fail’,
             op2 => ‘success’,
             op3 => ‘unknown’,
     );
     my %ops_from_anon2 = (
       op4 => 'unknown',
     );
     my @primer_grup_ops = ('anon1', %ops_from_anon1);
     my @segon_grup_ops = ('anon2', %ops_from_anon2);
     my @ops = (@primer_grup_ops, @segon_grup_ops);

     foreach my $op (@ops) {
         print "Origen: $$op[0] n";
         print "t Nom de la op: $_, estat: ${ $$op[1] }{$_} n"
                    foreach keys %{ $$op[1] };
     }



sábado 12 de noviembre de 2011
Notació alternativa:
                                 the dereferencing arrow
     my %ops_from_anon1 = (
             op1 => ‘fail’,
             op2 => ‘success’,
             op3 => ‘unknown’,
     );
     my %ops_from_anon2 = (
       op4 => 'unknown',
     );
     my @primer_grup_ops = ('anon1', %ops_from_anon1);
     my @segon_grup_ops = ('anon2', %ops_from_anon2);
     my @ops = (@primer_grup_ops, @segon_grup_ops);

     foreach my $op (@ops) {
         print "Origen: $op->[0] n";
         print "t Nom de la op: $_, estat: $op->[1]->{$_} n"
                    foreach keys %{$op->[1]};
     }



sábado 12 de noviembre de 2011
Array i Hash   anònims
                                     Array: [ ... ]
                                      Hash: { ... }

     my @ops = (
         ['anon1', {                op1   =>   'fail',
              ! !                   op2   =>   'success',
              ! !                   op3   =>   'unknown', }],
         ['anon2', {                op4   =>   'unknown', }]
         );

     foreach my $op (@ops) {
         print "Origen: $op->[0] n";
         print "t Nom de la op: $_, estat: $op->[1]->{$_} n"
                    foreach keys %{$op->[1]};
     }




sábado 12 de noviembre de 2011
Però s’ha d’anar amb una mica de compte:

  my @llista = qw< anon1 anon2 anon3 >;
  my $llista1_ref = @llista;
  my $llista2_ref = @llista;
  push @llista, 'anon4';

...tant @$llista1_ref com @$llista2_ref tenen un servidor nou, però...

  my @llista = qw< anon1 anon2 anon3 >;
  my $llista1_ref = [ @llista ];
  my $llista2_ref = [ @llista ];
  push @llista, 'anon4';

...ni @$llista1_ref ni @$llista2_ref tenen cap servidor nou afegit




sábado 12 de noviembre de 2011
Autovivificació

     La idea és que si des-referenciem una variable
     escalar -que conté undef- com si fos una
     referència a un array, se li assignarà una
     referència a un array anònim buit i es procedirà
     amb l’execució del codi.

     El mateix passarà amb un hash, si ens trobem una
     variable de valor undef que es des-referenciada
     com si fos una referència a un hash, s’assigna un
     hash anònim buit i l’execució continuarà.




sábado 12 de noviembre de 2011
Autovivificació

     my $ops;
     $ops->[0]->[0] = 'anon1';
     $ops->[1]->[0] = 'anon2';
     $ops->[0]->[1]->{'op1'} =      'fail';
     $ops->[0]->[1]->{'op2'} =      'success';
     $ops->[0]->[1]->{'op3'} =      'unknown';
     $ops->[1]->[1]->{'op4'} =      'unknown';

     foreach my $op (@$ops) {
         print "Origen: $op->[0] n";
         print "t Nom de la op: $_, estat: $op->[1]->{$_} n"
                  foreach keys %{$op->[1]};
     }




sábado 12 de noviembre de 2011
if the arrow ends up between "subscripty kinds of
     things" such as square brackets, we can also drop
                         the arrow.

     my $ops;
     $ops->[0][0] = 'anon1';
     $ops->[1][0] = 'anon2';
     $ops->[0][1]{'op1'} = 'fail';
     $ops->[0][1]{'op2'} = 'success';
     $ops->[0][1]{'op3'} = 'unknown';
     $ops->[1][1]{'op4'} = 'unknown';

     foreach my $op (@$ops) {
         print "Origen: $op->[0] n";
         print "t Nom de la op: $_, estat: $op->[1]{$_} n"
                  foreach keys %{$op->[1]};
     }




sábado 12 de noviembre de 2011
Problemes:


                                         Aliasing
                                        (as usual)

                                 Comptatge de referències
                                 (no garbage collection)




sábado 12 de noviembre de 2011
SUB-RU-TI-NES
                        (no funcions, ni procediments, ni mètodes, ni...)




sábado 12 de noviembre de 2011
SUB-RU-TI-NES
                        (no funcions, ni procediments, ni mètodes, ni...)


                     Spock: Cadet Kirk, you somehow managed to install and activate a subroutine in the
                     programming code, thereby changing the conditions of the test.
                     James T. Kirk: Your point being?
                     Admiral Richard Barnett: In academic vernacular, you cheated.
                                                                                              Star Trek (2009)




sábado 12 de noviembre de 2011
SUB-RU-TI-NES
                        (no funcions, ni procediments, ni mètodes, ni...)


                     Spock: Cadet Kirk, you somehow managed to install and activate a subroutine in the
                     programming code, thereby changing the conditions of the test.
                     James T. Kirk: Your point being?
                     Admiral Richard Barnett: In academic vernacular, you cheated.
                                                                                              Star Trek (2009)


                     Kim: She's not a member of the crew. She's a character on the holodeck.
                     Tuvok: You're in love with a computer subroutine?
                     Kim: That's the problem.
                     Tuvok: Interesting.
                                                                   Star Trek Voyager, ‘Alter Ego’ S03E14 (1997)




sábado 12 de noviembre de 2011
SUB-RU-TI-NES
                        (no funcions, ni procediments, ni mètodes, ni...)


                     Spock: Cadet Kirk, you somehow managed to install and activate a subroutine in the
                     programming code, thereby changing the conditions of the test.
                     James T. Kirk: Your point being?
                     Admiral Richard Barnett: In academic vernacular, you cheated.
                                                                                              Star Trek (2009)


                     Kim: She's not a member of the crew. She's a character on the holodeck.
                     Tuvok: You're in love with a computer subroutine?
                     Kim: That's the problem.
                     Tuvok: Interesting.
                                                                   Star Trek Voyager, ‘Alter Ego’ S03E14 (1997)


                     Lt. Cmdr. Data: You are much more than that, Jenna. I have written a subroutine specifically
                     for you - a program within the program. I have devoted a considerable share of my internal
                     resources to its development.
                     Lt. Jenna D'Sora: Data... that's the nicest thing anybody's ever said to me.
                                                         Star Trek The Next Generation, ‘In Theory’ S04E25 (1991)




sábado 12 de noviembre de 2011
Subrutines

  Declaració:

           sub nom_de_la_subrutina { . . . }



  Invocació:

           nom_de_la_subrutina ( ... )

               #    de vegades podem prescindir dels parèntesi, però millor
               #    que no (som moderns :-))
               #
               #    de vegades cal posar un ampersand (&) davant del nom, però
               #    si no anomenem cap subrutina igual que una subrutina de perl
               #    no ha d’haver cap problema




sábado 12 de noviembre de 2011
Subrutines
  Pas de paràmetres:

           nom_de_la_subrutina ( ... )
             # en el moment de la crida, tots els paràmetres es disposen
             # en un array d’escalars (flattening)
             # que es veu des de dins de la subrutina com l’array @_

  exemple:
                                 #   hanoi(N, start, end, extra)
                                 #   Solve Tower of Hanoi problem for a tower of N disks,
                                 #   of which the largest is disk #N. Move the entire tower from
                                 #   peg 'start' to peg 'end', using peg 'extra' as a work space

                                 sub hanoi {
                                   my ($n, $start, $end, $extra) = @_;
                                   if ($n == 1) {
                                     print "Move disk #1 from $start to $end.n";               # Step 1
                                   } else {
                                     hanoi($n-1, $start, $extra, $end);                         # Step 2
                                     print "Move disk #$n from $start to $end.n";              # Step 3
                                     hanoi($n-1, $extra, $end, $start);                         # Step 4
                                 } }


                    (from Higher-Order Perl by Mark Dominus, published by Morgan Kaufmann Publishers, Copyright 2005 by Elsevier Inc)




sábado 12 de noviembre de 2011
Pas de paràmetres:

           nom_de_la_subrutina ( ... )
             # pas de paràmetres per valor? per referència?
             # En realitat @_ conté alias dels paràmetres originals, així,
             # si modifiquem $_[i] estarem modificant el paràmetre i-èssim
             # real. En canvi, en assignar-los, els paràmetres reals es
             # copien

  exemple:
         sub modifica_nom1 {                 sub modifica_nom2 {
            $_[0] = reverse($_[0]);             my $temp = shift;
         }                                      $temp = reverse $temp;
                                             }
                    my $nom = 'Jordi';       my $nom = 'Jordi';
                    modifica_nom1( $nom );   modifica_nom2( $nom );
                    print $nom, “n”;        print $nom, “n”;

                                 idroJ            Jordi




sábado 12 de noviembre de 2011
Accés als paràmetres:

                                 sub hanoi {
                                   my ($n, $start, $end, $extra) = @_;
                                   if ($n == 1) {
                                     print "Move disk #1 from $start to $end.n";   # Step 1
                                   } else ( . . . )




       The dominant practice seems to be to use shift only when your
      function must access a single parameter and list assignment when
                       accessing multiple parameters.



    Què retorna una subrutina?

                           Allò que s’ha calculat tot just abans d’acabar
                                                o bé
                            allò que és explícitament retornat amb return




sábado 12 de noviembre de 2011
Lexicals:

 El 'my' que hem vist davant de les variables
 quan les feiem servir per primera vegada li
 diu a perl que aquelles variables són locals
 al bloc més proper que conté el 'my'...

 ... i això és perque ...

 totes les variables són globals, per defecte.




sábado 12 de noviembre de 2011
* Retorn de valors no escalars:

 No hi ha cap diferència. Es poden retornar
 elements que no siguin escalars exactament de
 la mateixa manera. També podem retornar
 referències.

 * Context?

 Una subrutina pot conèixer el context en el
 que ha estat cridada gràcies a wantarray:

                   wantarray() -> undef si el context és void
                   wantarray() -> true si el context és llista
                   wantarray() -> false si el context és escalar




sábado 12 de noviembre de 2011
Referències a subrutines (coderefs):
              my $ref = &nom_de_subrutina;
                  # ampersand obligatori! també, només volem el nom

                        ...

              $ref->(p1,p2,...)
                  # equivalent a nom_de_subrutina(p1,p2,...)
                  # fixem-nos en la dereferencing arrow


     A partir del moment en que puc manipular
     referències a funcions, ja puc emmagatzemar-les,
     retornar-les, passar-les com a paràmetre... són
     ciutadans de primera classe (en realitat no, però
     si).



sábado 12 de noviembre de 2011
Subrutines                        anònimes
              my $ref_a_subrutina = sub { . . . }
                  # el cos de la subrutina no té res d’especial
                  # el resultat és una referència a una subrutina



     Closures (tancaments lexics):
                                 sub simple_demo {
                                      my $privatecounter = 0;
                                      return sub { $privatecounter++ };
                                 }

                                 my $demo1 = simple_demo;
                                 my $demo2 = simple_demo;
                                 foreach (0..5) {
                                    print $demo1->(), “n”;
                                    print $demo2->(), “n”;
                                 }



sábado 12 de noviembre de 2011
sábado 12 de noviembre de 2011
Problema: Memoització
     Fer una funció memoize on donada una ref. a una funció f, retorni
     una ref. a una funció g que calculi el mateix que f, però
     emmagatzemi allò que calcula, de manera que no ho calculi
     explícitament mai dues vegades.


     Solució:
                                 sub memoize {
                                      my ($func) = @_;
                                      my %cache;
                                      return sub {
                                                 my $key = join ‘,’ , @_;
                                                 $cache{$key} = $func->(@_)
                                                       unless exists $cache{$key};
                                                 return $cache{$key};
                                             };
                                 }




sábado 12 de noviembre de 2011
Problema: map
     Si llista és (l1, l2, l3,...) fer una funció map tal que
            map (&f, llista) -> (f(l1), f(l2), f(l3),...)


     Solució:
                                 sub map {
                                     my $func = shift;
                                     my @result = ();
                                     foreach (@_) {
                                        push @result, $func->($_);
                                     }
                                     return @result;
                                 }




sábado 12 de noviembre de 2011
Problema: grep
     Si llista és (l1, l2, l3,...) i f és una funció amb resultat
     booleà (diguem, {0,1}) fer una funció grep tal que
            grep (&f, llista) -> (li, lj, lk,...)
     on els li, lj, lk,... són aquells elements de la llista tals que
     quan se’ls aplica f el resultat és 1.


     Solució:
                                 sub grep {
                                     my $func = shift;
                                     my @result = ();
                                     foreach (@_) {
                                        push(@result, $_) if $func->($_);
                                     }
                                     return @result;
                                 }




sábado 12 de noviembre de 2011
Problema: inject
     Si llista és (l1, l2, l3,...) fer una funció inject tal que
     inject (&f, escalar, llista) ->
                     f(... f(f(f(escalar,l1),l2),l3) ...)


     Solució:
                                 sub inject {
                                     my $func = shift;
                                     my $escalar = shift;
                                     my $result = $escalar;
                                     foreach (@_) {
                                        $result = $func->($result,$_);
                                     }
                                     return $result;
                                 }




sábado 12 de noviembre de 2011

Contenu connexe

En vedette

Sybase SQL AnyWhere12
Sybase SQL AnyWhere12Sybase SQL AnyWhere12
Sybase SQL AnyWhere12Sunny U Okoro
 
Executive Summary Mid-Day Meals July 2012
Executive Summary Mid-Day Meals July 2012Executive Summary Mid-Day Meals July 2012
Executive Summary Mid-Day Meals July 2012KusumaTrustUK
 
Cilc2013 .hr.wk.ewv 20130314
Cilc2013 .hr.wk.ewv 20130314Cilc2013 .hr.wk.ewv 20130314
Cilc2013 .hr.wk.ewv 20130314Heimo Rainer
 
The Flying Scotsman - Trailer em fotos
The Flying Scotsman - Trailer em fotosThe Flying Scotsman - Trailer em fotos
The Flying Scotsman - Trailer em fotosJonisousa Campos
 
Jn1033 globalisation
Jn1033 globalisationJn1033 globalisation
Jn1033 globalisationMegan Knight
 
Intro to press regulation
Intro to press regulationIntro to press regulation
Intro to press regulationnctcmedia12
 
Two way fine art pen & brush
Two way fine art pen & brushTwo way fine art pen & brush
Two way fine art pen & brushibec546
 
фотоотчет акции памяти
фотоотчет акции памятифотоотчет акции памяти
фотоотчет акции памятиViktoriya Donchik
 
Възможности за финансиране по ОПК (Оперативна Програма Конкурентноспособност)...
Възможности за финансиране по ОПК (Оперативна Програма Конкурентноспособност)...Възможности за финансиране по ОПК (Оперативна Програма Конкурентноспособност)...
Възможности за финансиране по ОПК (Оперативна Програма Конкурентноспособност)...Moite Pari
 
Проект "Йододефецит"
Проект "Йододефецит"Проект "Йододефецит"
Проект "Йододефецит"Viktoriya Donchik
 
Опрыскиватель ранцевый аккумуляторный Solo 416
Опрыскиватель ранцевый аккумуляторный Solo 416Опрыскиватель ранцевый аккумуляторный Solo 416
Опрыскиватель ранцевый аккумуляторный Solo 416Al Maks
 
Proizvodstvo i tekhnologii_poritep
Proizvodstvo i tekhnologii_poritepProizvodstvo i tekhnologii_poritep
Proizvodstvo i tekhnologii_poritepAl Maks
 
"Marketinq AIR" 2 praktiki marketinq təlimləri
"Marketinq AIR" 2 praktiki marketinq təlimləri"Marketinq AIR" 2 praktiki marketinq təlimləri
"Marketinq AIR" 2 praktiki marketinq təlimləriRafig Valiyev
 

En vedette (19)

Sybase SQL AnyWhere12
Sybase SQL AnyWhere12Sybase SQL AnyWhere12
Sybase SQL AnyWhere12
 
Executive Summary Mid-Day Meals July 2012
Executive Summary Mid-Day Meals July 2012Executive Summary Mid-Day Meals July 2012
Executive Summary Mid-Day Meals July 2012
 
Cilc2013 .hr.wk.ewv 20130314
Cilc2013 .hr.wk.ewv 20130314Cilc2013 .hr.wk.ewv 20130314
Cilc2013 .hr.wk.ewv 20130314
 
The Flying Scotsman - Trailer em fotos
The Flying Scotsman - Trailer em fotosThe Flying Scotsman - Trailer em fotos
The Flying Scotsman - Trailer em fotos
 
Jn1033 globalisation
Jn1033 globalisationJn1033 globalisation
Jn1033 globalisation
 
Intro to press regulation
Intro to press regulationIntro to press regulation
Intro to press regulation
 
Mbc student layout
Mbc student layoutMbc student layout
Mbc student layout
 
Two way fine art pen & brush
Two way fine art pen & brushTwo way fine art pen & brush
Two way fine art pen & brush
 
Trp no 21 final jun 15
Trp no 21 final jun 15  Trp no 21 final jun 15
Trp no 21 final jun 15
 
фотоотчет акции памяти
фотоотчет акции памятифотоотчет акции памяти
фотоотчет акции памяти
 
Going green
Going greenGoing green
Going green
 
Nuklir speaking
Nuklir speakingNuklir speaking
Nuklir speaking
 
Lugo
LugoLugo
Lugo
 
Възможности за финансиране по ОПК (Оперативна Програма Конкурентноспособност)...
Възможности за финансиране по ОПК (Оперативна Програма Конкурентноспособност)...Възможности за финансиране по ОПК (Оперативна Програма Конкурентноспособност)...
Възможности за финансиране по ОПК (Оперативна Програма Конкурентноспособност)...
 
Проект "Йододефецит"
Проект "Йододефецит"Проект "Йододефецит"
Проект "Йододефецит"
 
Опрыскиватель ранцевый аккумуляторный Solo 416
Опрыскиватель ранцевый аккумуляторный Solo 416Опрыскиватель ранцевый аккумуляторный Solo 416
Опрыскиватель ранцевый аккумуляторный Solo 416
 
Franchise
FranchiseFranchise
Franchise
 
Proizvodstvo i tekhnologii_poritep
Proizvodstvo i tekhnologii_poritepProizvodstvo i tekhnologii_poritep
Proizvodstvo i tekhnologii_poritep
 
"Marketinq AIR" 2 praktiki marketinq təlimləri
"Marketinq AIR" 2 praktiki marketinq təlimləri"Marketinq AIR" 2 praktiki marketinq təlimləri
"Marketinq AIR" 2 praktiki marketinq təlimləri
 

Referències i Subrutines

  • 1. Referències & Subrutines Jordi Delgado Curs BCN Perl Mongers 5 Novembre 2011 remember, remember the fifth of November... sábado 12 de noviembre de 2011
  • 2. Els Array i els Hash poden contenir només escalars... Com podem construir estructures de dades complexes? sábado 12 de noviembre de 2011
  • 3. doncs com sempre... amb punters! referències = punters sábado 12 de noviembre de 2011
  • 4. Operador referència: Context escalar: referència Context llista: llista de referències Una referència és un escalar sábado 12 de noviembre de 2011
  • 5. exemples: my $nom = ‘anonymous’; my $nom_ref = $nom; # referència a escalar my @llista = qw< anon1 anon2 anon3 >; my $llista_ref = @llista # referència a array my $aliased_llista = $llista_ref; my %diccionari = ( op1 => ‘fail’, op2 => ‘success’, op3 => ‘unknown’, op4 => ‘unknown’ ); my $diccionari_ref = %diccionari; # referència a hash my $aliased_diccionari = $diccionari_ref; sábado 12 de noviembre de 2011
  • 6. Des-referenciar: afegir un sigil més que dependrà d’allò referenciat, utilitzant claus envoltant la referència my @llista = qw< anon1 anon2 anon3 >; my $llista_ref = @llista # referència a array my $aliased_llista = $llista_ref; print "@{ $llista_ref } n"; my %diccionari = ( op1 => ‘fail’, op2 => ‘success’, op3 => ‘unknown’, op4 => ‘unknown’ ); my $diccionari_ref = %diccionari; # referència a hash my $aliased_diccionari = $diccionari_ref; print keys %{ $diccionari_ref } , "n"; print values %{ $diccionari_ref } , "n"; sábado 12 de noviembre de 2011
  • 7. Però, si el que volem des-referenciar és només una variable escalar no fan falta les claus {} @{ $llista_ref } = @$llista_ref ${ $llista_ref }[0] = $$llista_ref[0] print $$llista_ref[$_], "n" foreach (0..$#$llista_ref) %{ $diccionari_ref } = %$diccionari_ref ${ $diccionari_ref }{'op2'} = $$diccionari_ref{'op2'} print $$diccionari_ref{$_}, "n" foreach keys %$diccionari_ref; farem servir les claus {} només per desambiguar, quan calgui sábado 12 de noviembre de 2011
  • 8. Ara ja podem construir estructures de dades complexes: my %ops_from_anon1 = ( op1 => ‘fail’, op2 => ‘success’, op3 => ‘unknown’, ); my %ops_from_anon2 = ( op4 => 'unknown', ); my @primer_grup_ops = ('anon1', %ops_from_anon1); my @segon_grup_ops = ('anon2', %ops_from_anon2); my @ops = (@primer_grup_ops, @segon_grup_ops); foreach my $op (@ops) { print "Origen: $$op[0] n"; print "t Nom de la op: $_, estat: ${ $$op[1] }{$_} n" foreach keys %{ $$op[1] }; } sábado 12 de noviembre de 2011
  • 9. Notació alternativa: the dereferencing arrow my %ops_from_anon1 = ( op1 => ‘fail’, op2 => ‘success’, op3 => ‘unknown’, ); my %ops_from_anon2 = ( op4 => 'unknown', ); my @primer_grup_ops = ('anon1', %ops_from_anon1); my @segon_grup_ops = ('anon2', %ops_from_anon2); my @ops = (@primer_grup_ops, @segon_grup_ops); foreach my $op (@ops) { print "Origen: $op->[0] n"; print "t Nom de la op: $_, estat: $op->[1]->{$_} n" foreach keys %{$op->[1]}; } sábado 12 de noviembre de 2011
  • 10. Array i Hash anònims Array: [ ... ] Hash: { ... } my @ops = ( ['anon1', { op1 => 'fail', ! ! op2 => 'success', ! ! op3 => 'unknown', }], ['anon2', { op4 => 'unknown', }] ); foreach my $op (@ops) { print "Origen: $op->[0] n"; print "t Nom de la op: $_, estat: $op->[1]->{$_} n" foreach keys %{$op->[1]}; } sábado 12 de noviembre de 2011
  • 11. Però s’ha d’anar amb una mica de compte: my @llista = qw< anon1 anon2 anon3 >; my $llista1_ref = @llista; my $llista2_ref = @llista; push @llista, 'anon4'; ...tant @$llista1_ref com @$llista2_ref tenen un servidor nou, però... my @llista = qw< anon1 anon2 anon3 >; my $llista1_ref = [ @llista ]; my $llista2_ref = [ @llista ]; push @llista, 'anon4'; ...ni @$llista1_ref ni @$llista2_ref tenen cap servidor nou afegit sábado 12 de noviembre de 2011
  • 12. Autovivificació La idea és que si des-referenciem una variable escalar -que conté undef- com si fos una referència a un array, se li assignarà una referència a un array anònim buit i es procedirà amb l’execució del codi. El mateix passarà amb un hash, si ens trobem una variable de valor undef que es des-referenciada com si fos una referència a un hash, s’assigna un hash anònim buit i l’execució continuarà. sábado 12 de noviembre de 2011
  • 13. Autovivificació my $ops; $ops->[0]->[0] = 'anon1'; $ops->[1]->[0] = 'anon2'; $ops->[0]->[1]->{'op1'} = 'fail'; $ops->[0]->[1]->{'op2'} = 'success'; $ops->[0]->[1]->{'op3'} = 'unknown'; $ops->[1]->[1]->{'op4'} = 'unknown'; foreach my $op (@$ops) { print "Origen: $op->[0] n"; print "t Nom de la op: $_, estat: $op->[1]->{$_} n" foreach keys %{$op->[1]}; } sábado 12 de noviembre de 2011
  • 14. if the arrow ends up between "subscripty kinds of things" such as square brackets, we can also drop the arrow. my $ops; $ops->[0][0] = 'anon1'; $ops->[1][0] = 'anon2'; $ops->[0][1]{'op1'} = 'fail'; $ops->[0][1]{'op2'} = 'success'; $ops->[0][1]{'op3'} = 'unknown'; $ops->[1][1]{'op4'} = 'unknown'; foreach my $op (@$ops) { print "Origen: $op->[0] n"; print "t Nom de la op: $_, estat: $op->[1]{$_} n" foreach keys %{$op->[1]}; } sábado 12 de noviembre de 2011
  • 15. Problemes: Aliasing (as usual) Comptatge de referències (no garbage collection) sábado 12 de noviembre de 2011
  • 16. SUB-RU-TI-NES (no funcions, ni procediments, ni mètodes, ni...) sábado 12 de noviembre de 2011
  • 17. SUB-RU-TI-NES (no funcions, ni procediments, ni mètodes, ni...) Spock: Cadet Kirk, you somehow managed to install and activate a subroutine in the programming code, thereby changing the conditions of the test. James T. Kirk: Your point being? Admiral Richard Barnett: In academic vernacular, you cheated. Star Trek (2009) sábado 12 de noviembre de 2011
  • 18. SUB-RU-TI-NES (no funcions, ni procediments, ni mètodes, ni...) Spock: Cadet Kirk, you somehow managed to install and activate a subroutine in the programming code, thereby changing the conditions of the test. James T. Kirk: Your point being? Admiral Richard Barnett: In academic vernacular, you cheated. Star Trek (2009) Kim: She's not a member of the crew. She's a character on the holodeck. Tuvok: You're in love with a computer subroutine? Kim: That's the problem. Tuvok: Interesting. Star Trek Voyager, ‘Alter Ego’ S03E14 (1997) sábado 12 de noviembre de 2011
  • 19. SUB-RU-TI-NES (no funcions, ni procediments, ni mètodes, ni...) Spock: Cadet Kirk, you somehow managed to install and activate a subroutine in the programming code, thereby changing the conditions of the test. James T. Kirk: Your point being? Admiral Richard Barnett: In academic vernacular, you cheated. Star Trek (2009) Kim: She's not a member of the crew. She's a character on the holodeck. Tuvok: You're in love with a computer subroutine? Kim: That's the problem. Tuvok: Interesting. Star Trek Voyager, ‘Alter Ego’ S03E14 (1997) Lt. Cmdr. Data: You are much more than that, Jenna. I have written a subroutine specifically for you - a program within the program. I have devoted a considerable share of my internal resources to its development. Lt. Jenna D'Sora: Data... that's the nicest thing anybody's ever said to me. Star Trek The Next Generation, ‘In Theory’ S04E25 (1991) sábado 12 de noviembre de 2011
  • 20. Subrutines Declaració: sub nom_de_la_subrutina { . . . } Invocació: nom_de_la_subrutina ( ... ) # de vegades podem prescindir dels parèntesi, però millor # que no (som moderns :-)) # # de vegades cal posar un ampersand (&) davant del nom, però # si no anomenem cap subrutina igual que una subrutina de perl # no ha d’haver cap problema sábado 12 de noviembre de 2011
  • 21. Subrutines Pas de paràmetres: nom_de_la_subrutina ( ... ) # en el moment de la crida, tots els paràmetres es disposen # en un array d’escalars (flattening) # que es veu des de dins de la subrutina com l’array @_ exemple: # hanoi(N, start, end, extra) # Solve Tower of Hanoi problem for a tower of N disks, # of which the largest is disk #N. Move the entire tower from # peg 'start' to peg 'end', using peg 'extra' as a work space sub hanoi { my ($n, $start, $end, $extra) = @_; if ($n == 1) { print "Move disk #1 from $start to $end.n"; # Step 1 } else { hanoi($n-1, $start, $extra, $end); # Step 2 print "Move disk #$n from $start to $end.n"; # Step 3 hanoi($n-1, $extra, $end, $start); # Step 4 } } (from Higher-Order Perl by Mark Dominus, published by Morgan Kaufmann Publishers, Copyright 2005 by Elsevier Inc) sábado 12 de noviembre de 2011
  • 22. Pas de paràmetres: nom_de_la_subrutina ( ... ) # pas de paràmetres per valor? per referència? # En realitat @_ conté alias dels paràmetres originals, així, # si modifiquem $_[i] estarem modificant el paràmetre i-èssim # real. En canvi, en assignar-los, els paràmetres reals es # copien exemple: sub modifica_nom1 { sub modifica_nom2 { $_[0] = reverse($_[0]); my $temp = shift; } $temp = reverse $temp; } my $nom = 'Jordi'; my $nom = 'Jordi'; modifica_nom1( $nom ); modifica_nom2( $nom ); print $nom, “n”; print $nom, “n”; idroJ Jordi sábado 12 de noviembre de 2011
  • 23. Accés als paràmetres: sub hanoi { my ($n, $start, $end, $extra) = @_; if ($n == 1) { print "Move disk #1 from $start to $end.n"; # Step 1 } else ( . . . ) The dominant practice seems to be to use shift only when your function must access a single parameter and list assignment when accessing multiple parameters. Què retorna una subrutina? Allò que s’ha calculat tot just abans d’acabar o bé allò que és explícitament retornat amb return sábado 12 de noviembre de 2011
  • 24. Lexicals: El 'my' que hem vist davant de les variables quan les feiem servir per primera vegada li diu a perl que aquelles variables són locals al bloc més proper que conté el 'my'... ... i això és perque ... totes les variables són globals, per defecte. sábado 12 de noviembre de 2011
  • 25. * Retorn de valors no escalars: No hi ha cap diferència. Es poden retornar elements que no siguin escalars exactament de la mateixa manera. També podem retornar referències. * Context? Una subrutina pot conèixer el context en el que ha estat cridada gràcies a wantarray: wantarray() -> undef si el context és void wantarray() -> true si el context és llista wantarray() -> false si el context és escalar sábado 12 de noviembre de 2011
  • 26. Referències a subrutines (coderefs): my $ref = &nom_de_subrutina; # ampersand obligatori! també, només volem el nom ... $ref->(p1,p2,...) # equivalent a nom_de_subrutina(p1,p2,...) # fixem-nos en la dereferencing arrow A partir del moment en que puc manipular referències a funcions, ja puc emmagatzemar-les, retornar-les, passar-les com a paràmetre... són ciutadans de primera classe (en realitat no, però si). sábado 12 de noviembre de 2011
  • 27. Subrutines anònimes my $ref_a_subrutina = sub { . . . } # el cos de la subrutina no té res d’especial # el resultat és una referència a una subrutina Closures (tancaments lexics): sub simple_demo { my $privatecounter = 0; return sub { $privatecounter++ }; } my $demo1 = simple_demo; my $demo2 = simple_demo; foreach (0..5) { print $demo1->(), “n”; print $demo2->(), “n”; } sábado 12 de noviembre de 2011
  • 28. sábado 12 de noviembre de 2011
  • 29. Problema: Memoització Fer una funció memoize on donada una ref. a una funció f, retorni una ref. a una funció g que calculi el mateix que f, però emmagatzemi allò que calcula, de manera que no ho calculi explícitament mai dues vegades. Solució: sub memoize { my ($func) = @_; my %cache; return sub { my $key = join ‘,’ , @_; $cache{$key} = $func->(@_) unless exists $cache{$key}; return $cache{$key}; }; } sábado 12 de noviembre de 2011
  • 30. Problema: map Si llista és (l1, l2, l3,...) fer una funció map tal que map (&f, llista) -> (f(l1), f(l2), f(l3),...) Solució: sub map { my $func = shift; my @result = (); foreach (@_) { push @result, $func->($_); } return @result; } sábado 12 de noviembre de 2011
  • 31. Problema: grep Si llista és (l1, l2, l3,...) i f és una funció amb resultat booleà (diguem, {0,1}) fer una funció grep tal que grep (&f, llista) -> (li, lj, lk,...) on els li, lj, lk,... són aquells elements de la llista tals que quan se’ls aplica f el resultat és 1. Solució: sub grep { my $func = shift; my @result = (); foreach (@_) { push(@result, $_) if $func->($_); } return @result; } sábado 12 de noviembre de 2011
  • 32. Problema: inject Si llista és (l1, l2, l3,...) fer una funció inject tal que inject (&f, escalar, llista) -> f(... f(f(f(escalar,l1),l2),l3) ...) Solució: sub inject { my $func = shift; my $escalar = shift; my $result = $escalar; foreach (@_) { $result = $func->($result,$_); } return $result; } sábado 12 de noviembre de 2011