← Perl EspañolChapter 05 of 13

Funciones

## Objetivos de Aprendizaje - Crear y llamar funciones (subrutinas) - Pasar parametros y valores de retorno - Comprender wantarray para contexto - Dominar closures y funciones anonimas - Usar funciones con prototipos ## Subrutinas ### Declaracion ```perl use strict; use warnings; sub saludar { print "Hola!\n"; } saludar(); # Llamar la subrutina ``` ### Nomenclatura ```perl sub decir_hola { } sub decir_hola_mundo { } sub con_guion_bajo { } sub mixedCase { } # La convencion de Perl es snake_case ``` ### Llamando ```perl # Con parentesis saludar(); saludar; # Con argumentos saludar("Alice"); saludar "Alice"; # Sin parentesis ``` ## Parametros ### Arreglo @_ ```perl use strict; use warnings; sub saludar { my ($nombre) = @_; # Desempaquetar parametros print "Hola, $nombre!\n"; } saludar("Alice"); # Hola, Alice! ``` ### Multiples Parametros ```perl sub sumar { my ($a, $b) = @_; return $a + $b; } print sumar(5, 3); # 8 ``` ### Parametros Flexibles ```perl sub sumar { my $total = 0; foreach my $val (@_) { $total += $val; } return $total; } print sumar(1, 2, 3, 4, 5); # 15 ``` ### Parametros Nombrados ```perl sub crear_usuario { my %params = @_; my $nombre = $params{nombre} // "Anonimo"; my $edad = $params{edad} // 0; return { nombre => $nombre, edad => $edad }; } my $usuario = crear_usuario(nombre => "Alice", edad => 30); ``` ### Parametros por Defecto ```perl sub saludar { my ($nombre, $saludo) = @_; $saludo //= "Hola"; print "$saludo, $nombre!\n"; } saludar("Alice"); # Hola, Alice! saludar("Bob", "Hola"); # Hola, Bob! ``` ## Valores de Retorno ### Return explicito ```perl sub max { my ($a, $b) = @_; if ($a > $b) { return $a; } return $b; } print max(5, 3); # 5 ``` ### Return Implicito ```perl sub obtener_valores { my @valores = (1, 2, 3); return @valores; # Contexto de lista } my @nums = obtener_valores(); # (1, 2, 3) sub obtener_primero { my ($a, $b) = @_; $a; # Ultima expresion retornada } my $primero = obtener_primero(5, 3); # 5 ``` ### Retornar Multiples Valores ```perl sub dividir { my ($a, $b) = @_; return (int($a / $b), $a % $b); } my ($cociente, $residuo) = dividir(10, 3); print "C: $cociente, R: $residuo\n"; # C: 3, R: 1 ``` ## Conciencia de Contexto ### wantarray ```perl sub obtener_valores { if (wantarray) { return ("contexto", "lista"); } elsif (defined wantarray) { return "escalar"; } else { return "void"; } } my @lista = obtener_valores(); # "contexto lista" my $escalar = obtener_valores(); # "escalar" obtener_valores(); # "void" ``` ### Ejemplo Practico ```perl sub obtener_datos { my @datos = (1, 2, 3); if (wantarray) { return @datos; } return \@datos; # Retornar referencia en contexto escalar } my @lista = obtener_datos(); # Lista my $ref = obtener_datos(); # Referencia ``` ## Pasando Referencias ### Referencias de Arreglo ```perl sub procesar_arreglo { my ($arr_ref) = @_; foreach my $elem (@$arr_ref) { print "$elem "; } print "\n"; } my @nums = (1, 2, 3); procesar_arreglo(\@nums); ``` ### Referencias de Hash ```perl sub procesar_hash { my ($hash_ref) = @_; foreach my $clave (keys %$hash_ref) { print "$clave => $hash_ref->{$clave}\n"; } } my %datos = (a => 1, b => 2); procesar_hash(\%datos); ``` ### Modificar Original ```perl sub duplicar_valores { my ($arr_ref) = @_; for my $i (0 .. $#$arr_ref) { $arr_ref->[$i] *= 2; } } my @nums = (1, 2, 3); duplicar_valores(\@nums); print "@nums\n"; # 2 4 6 ``` ## Closures ### Closure Basico ```perl use strict; use warnings; sub crear_contador { my $contador = 0; return sub { $contador++; return $contador; }; } my $contador = crear_contador(); print $contador->(); # 1 print $contador->(); # 2 print $contador->(); # 3 my $contador2 = crear_contador(); print $contador2->(); # 1 (contador separado) ``` ### Funcion de Fabrica ```perl sub multiplicador { my ($factor) = @_; return sub { my ($num) = @_; return $num * $factor; }; } my $doble = multiplicador(2); my $triple = multiplicador(3); print $doble->(5); # 10 print $triple->(5); # 15 ``` ### Variables de Estado (Perl 5.10+) ```perl use strict; use warnings; use 5.010; sub contador { state $contador = 0; # Estado persistente return ++$contador; } print contador(); # 1 print contador(); # 2 print contador(); # 3 ``` ## Funciones Anonymous ### Closures como Callbacks ```perl use strict; use warnings; my @numeros = (1, 2, 3, 4, 5); my @cuadrados = map { $_ * $_ } @numeros; print "@cuadrados\n"; # 1 4 9 16 25 my @pares = grep { $_ % 2 == 0 } @numeros; print "@pares\n"; # 2 4 ``` ### Subrutina Anonymous ```perl my $sumar = sub { my ($a, $b) = @_; return $a + $b; }; print $sumar->(5, 3); # 8 # O con desreferenciacion print &{ $sumar }(5, 3); # 8 ``` ## Prototipos ### Prototipos Basicos ```perl use strict; use warnings; sub mi_print($$) { # Espera dos escalares my ($str1, $str2) = @_; print $str1, $str2; } mi_print("Hola", " Mundo"); ``` ### Caracteres de Prototipo | Caracter | Significado | |----------|-------------| | `$` | Escalar | | `@` | Arreglo | | `%` | Hash | | `&` | Subrutina | | `*` | Typeglob | | `\` | Referencia | ### Problemas con Prototipos ```perl # Los prototipos no funcionan con llamadas a metodos # y pueden ser confusos. Usar con precauccion. # Mejor: parametros explicitos sub sumar { my ($a, $b) = @_; return $a + $b; } ``` ## Variables Especiales en Subrutinas ### Detalles de @_ ```perl sub inspeccionar_args { print "Numero de args: ", scalar(@_), "\n"; foreach my $i (0 .. $#_) { print " Arg $i: $_[$i]\n"; } } inspeccionar_args(1, "hola", 3.14); ``` ### Shift ```perl sub procesar { my $primero = shift; # Primer elemento my $segundo = shift; # Segundo elemento my @resto = @_; # Elementos restantes } ``` ## Recursion ```perl sub factorial { my ($n) = @_; return 1 if $n <= 1; return $n * factorial($n - 1); } print factorial(5); # 120 # Version iterativa sub factorial_iter { my ($n) = @_; my $resultado = 1; for my $i (2 .. $n) { $resultado *= $i; } return $resultado; } ``` ## Resumen - Subrutinas definidas con `sub nombre { }` - Parametros pasados via arreglo `@_` - Usa `my` para localizary desempquetar parametros - Valores de retorno con `return` o ultima expresion implicita - `wantarray` verifica el contexto de llamada - Los closures capturan variables lexicas - Subrutinas anonimas con `sub { }` - Referencias pasadas para arreglos/hashes a modificar - Variables `state` persisten entre llamadas (5.10+) - Los prototipos son opcionales y pueden ser problematicos

Comments

Comments powered by Giscus

To enable comments, add your Giscus embed code here.

Learn more about Giscus →