Diferencia entre revisiones de «Usuario:ManuelRomero/ProgramacionWeb/funciones»

De WikiEducator
Saltar a: navegación, buscar
(Funciones anónimas)
 
(5 revisiones intermedias por el mismo usuario no mostrado)
Línea 1: Línea 1:
 
<div id=parrafo>
 
<div id=parrafo>
<div class=slide>
 
==Funciones==
 
<br />
 
{{MRM_Objetivo|
 
;Las funciones es un elemento  fundamental
 
*Permite crear código modular
 
*Una forma de estructurar nuestro programa
 
}}
 
</div>
 
  
<div class=slide>
+
{{ManuelRomero/PHP/funciones}}
===Declaración de funciones===
+
{{ManuelRomero/PHP/funcionesRecursivas}}
<source lang=php>
+
{{ManuelRomero/PHP/funcionesAnonimas}}
// Declarar una función
+
{{ManuelRomero/PHP/funcionesFlecha}}
function nombre_de_funcion([tipo_de_parametro] $parametro_formal[=valor_por_defecto], ...)[: tipo_retorno]
+
{
+
    ...
+
    [return ...];
+
}
+
 
+
// Llamar
+
nombre_de_funcion($parametro_real);
+
</source>
+
 
+
</div>
+
<div class=slide>
+
*Es importante diferenciar entre declarar una función e invocar a una función
+
*Algo obvio, pero importante
+
*En la declaración tenemos tres partes
+
;nombre o identificación de la función
+
;parámetros_formales
+
*Se especifican entre paréntesisi(Estos han de existir, aunque no haya parámetros)
+
*Se puede especificar el tipo de cada parámetro (a partir de versión 7.2)
+
*Se puede asignar un valor por defecto (En este caso podría no aportarse valor para este parámetro en la invocación)
+
;Tipo de retorno
+
Es opcional
+
#Cuerpo de la función, dentro de él puede estar la instrucción return, en cuyo momento termina la ejecución de la función y se vuelve a la siguiente instrucción del programa, siguiente a la invocación de la función.
+
#El return puede (debe) aportar el valor que queremos que la función retorno
+
</div>
+
 
+
 
+
<div class=slide>
+
;Identificador de función
+
* El nombre de función es un identificador que empieza por una letra o guión bajo, seguido 0 o muchas letras, números o guiones bajos 
+
{{Tip|Expresión regular para el identificador de funciones
+
'''''[a-zA-Z_f_][a-zA-Z0-9_]*'''''
+
}}
+
</div>
+
<div class=slide>
+
;Parámetros formales
+
*Son nombres de variables que usaré al escribir el código o cuerpo de la función
+
*El nombre ha de ser significativo y se convertirán en variables locales a la función
+
*Una vez que se termina la función estas variables desaparecerán de memoria
+
{{MRM_Puntos clave|Title=parámetros formales|
+
Los parámetros formales son variables locales a la función}}
+
</div>
+
 
+
===Proceso de creación / invocación de una función===
+
;Lo primero es declarar una función
+
*Esto implica dejar una zona de memoria identificada con el nombre de la función
+
*En contenido de esas posiciones de memoria serán las acciones de la función
+
*Estas acciones estarán establecidas no con valores reales, sino con los parámetros de la declaración
+
*Estos parámetros se conocen como parámetros formales
+
[[Archivo:declaracion_funcion.png]]
+
;Invocación de función
+
*Es un tipo de instrucción, invocar a una acción o función.
+
[[Archivo:invocacion_funcion_1.png]]
+
*lo primero que ocurrirá es que voy a esa zona de memoria
+
[[Archivo:invocacion_funcion_2.png]]
+
*Lo siguiente es dar los valores reales (de la invocación) a los parámetros de la función (de la declaracion.
+
[[Archivo:invocacion_funcion_3.png]]
+
*Una vez que la función termina  de ejecutarse, se retornará a la instrucción siguiente de la invocación
+
*Si la función devuelve algún valor, se recogerá y asignará a la variable de la instrucción de asignación desde la cual se invocó
+
 
+
 
+
 
+
 
+
<div class=slide>
+
{{MRM_Actividad|Title=Ejercicio usando funciones|
+
'''''Haz un programa donde en el programa principal se creen dos variables $a y $b'''''
+
*Crea una función que reciba como parámetros locales '''''$a''''' y '''''$b'''''
+
*La función visualizará el valor de las variables, las modificará y las volverá a visualizar
+
*El programa principal
+
#asignará valor a las variables
+
#las visualizará
+
#invocará a la función
+
#volverá a visualizar las variables
+
}}
+
</div>
+
<div class=slide>
+
*Una posible solución
+
<source lang=php>    <?php
+
      function a($a, $b){
+
          echo "Dentro de la función visualizando valores <hr />";
+
          echo "Valor de los parámetros \$a = $a \$b = $b <br />";
+
          $a+=5;
+
          $b+=5;
+
          echo "Valor de los parámetros \$a = $a \$b = $b <br />";
+
          echo "Salgo de la función";
+
      }
+
      //Ahora considero programa principal
+
      $a=100;
+
      $b=200;
+
      echo "En el main antes de invocar a la función visualizando variables<hr />";
+
      echo "Valor de variables \$a = $a \$b = $b <br />";
+
      a($a,$b);
+
      echo "En el mail  después de invocar a la función visualizando variables<hr />";
+
      echo "Valor de variables \$a = $a \$b = $b <br />";
+
?>
+
</source>
+
</div>
+
 
+
<div class=slide>
+
 
+
===Parámetros formales: Valores y referencias===
+
*Cómo hemos visto, los parámetros formales son valores pasados en la invocación a la función
+
*Si queremos que la función pueda modificar el valor de los valores de los parámetros, en este caso hemos de pasarlos por referencia
+
*En este caso lo que ocurre en realidad es que pasamos la dirección de memoria dónde se guarda el valor.
+
*La dirección de memoria, no la podremos visualizar ni operar con ella, pues en php no existe la aritmética de punteros o direcciones de memoria
+
</div>
+
 
+
<div class=slide>
+
;Parámetros formales: Valores y referencias
+
Para pasar el parámetro por referencia, simplemente hay que poner el símbolo de dirección de memoria '''''&''''' antes del nombre de la variable en la declaración de parámetros
+
<source lang=php>
+
function nombre_funcion(&$paramRef1, &$paramRef2, $paramVal1){
+
  ...
+
}
+
</source>
+
</div>
+
 
+
 
+
<div class=slide>
+
{{MRM_Actividad|Title=Ejercicio usando funciones parámetros|
+
'''''Haz un programa donde en el programa principal se creen dos variables $a y $b y $c'''''
+
*Crea una función que reciba como parámetros locales '''''&$num1''''','''''&$num2''''' y '''''$num3'''''
+
*La función visualizará el valor de las variables, las modificará y las volverá a visualizar
+
*El programa principal
+
#asignará valor a las variables
+
#las visualizará
+
#invocará a la función
+
#volverá a visualizar las variables
+
}}
+
</div>
+
<source lang=php>
+
 
+
  <?php
+
      function a(&$num1, &$num2, $num3){
+
          echo "Dentro de la función visibilizando valores <hr />";
+
          echo "Valor de los parámetros \$num1 = $num1 \$num2 = $num2 \$num3 = $num3<br />";
+
          $num1+=5;
+
          $num2+=5;
+
          $num3+=5;
+
         
+
          echo "Valor de los parámetros \$num1 = $num1 \$num2 = $num2 \$num3 = $num3<br />";
+
          echo "Salgo de la función";
+
      }
+
      //Ahora considero programa principal
+
      $a=100;
+
      $b=200;
+
      $c=300;
+
      echo "En el main antes de invocar a la función visualizando variables<hr />";
+
      echo "Valor de variables \$a = $a \$b = $b \$c = $c <br />";
+
      a($a,$b,$c);
+
      echo "En el mail  después de invocar a la función visualizando variables<hr />";
+
      echo "Valor de variables \$a = $a \$b = $b \$c = $c <br />";
+
?>
+
</source>
+
<div class=slide>
+
;Invocando funciones
+
*Una vez creada una función la podemos invocar como si fuera una instrucción del lenguaje
+
*No sin razón en determinados ambientes se conoce a las funciones y procedimientos como instrucciones virtuales ...
+
*En php puedo invocar a una función antes de declararla, siempre que la declare en el mismo fichero
+
</div>
+
 
+
<div class=slide>
+
 
+
 
+
{{MRM_Ejemplo|Title = ejemplo invocación a funciones|
+
{{Tip|Este código funcionará correctamente}}
+
<source lang=php>
+
    <?php
+
      a(5,6); 
+
      /*Mas instrucciones*/
+
      function a ($a, $b){
+
          echo "valor de $a";
+
          echo "valor de $b";
+
      }
+
</source>
+
}}
+
</div>
+
 
+
<div class=slide>
+
 
+
{{MRM_Ejemplo|Title = ejemplo invocación a funciones|
+
{{Tip|Este código no  funcionará }}
+
<source lang=php>
+
<?php
+
      a(5,6); 
+
      /*Mas instrucciones*/
+
      include ("funciones.php");
+
?>
+
</source>
+
*Contenido del ficheor funciones.php
+
<source lang=php>
+
<?php
+
function a ($a, $b){
+
          echo "valor de $a";
+
          echo "valor de $b";
+
}
+
?>
+
</source>
+
}}
+
</div>
+
 
+
 
+
 
+
<div class="slide">
+
===Variables dentro de una función===
+
*Dentro de una función las variables que declaremos son locales a esa función.
+
*No podré acceder a su valor fuera de la función
+
*Esto también implica que dentro de una función no puedo acceder al valor de una variable definida fuera de la función
+
*Observa el siguiente ejemplo
+
<source lang=php>
+
<?php
+
 
+
 
+
function modifica_valor(){
+
    echo "Valor de <b>var1</b> dentro de función -$var1- <br /> ";
+
    $var1++;
+
    echo "Valor de <b>var1</b> dentro de función moficada -$var1- <br /> ";
+
}
+
 
+
$var1 = 20;
+
 
+
echo "Valor de <b>var1</b> en programa principal antes de invocar función: -$var1- <br />";
+
modifica_valor();
+
echo "Valor de <b>var1</b> en progrma principal después de invocar la función: -$var1- <br />";
+
?>
+
</source>
+
*Vemos que genera la siguiente salida
+
<source lang=bash>
+
Valor de var1 en programa principal antes de invocar función: -20-
+
Valor de var1 dentro de función --
+
Valor de var1 dentro de función moficada -1-
+
Valor de var1 en progrma principal después de invocar la función: -20-
+
</source>
+
*Sin embargo si quieremos acceder al valor de '''''$var ''''' dentro de la función, sí que podemos
+
*Hemos de usar la palabra reservada '''''$global'''''
+
<source lang=php>
+
<?php
+
 
+
function modifica_valor(){
+
    global $var1; //Indicamos que esta variables se puede globalizar
+
    echo "Valor de <b>var1</b> dentro de función -$var1- <br /> ";
+
    $var1++;
+
    echo "Valor de <b>var1</b> dentro de función moficada -$var1- <br /> ";
+
}
+
 
+
$var1 = 20;
+
 
+
echo "Valor de <b>var1</b> en programa principal antes de invocar función: -$var1- <br />";
+
modifica_valor();
+
echo "Valor de <b>var1</b> en progrma principal después de invocar la función: -$var1- <br />";
+
?>
+
</source>
+
*Ahora podemos observar cómo sí que se accede al valor dentro de la función
+
<source lang=bash>
+
Valor de var1 en programa principal antes de invocar función: -20-
+
Valor de var1 dentro de función -20-
+
Valor de var1 dentro de función moficada -21-
+
Valor de var1 en progrma principal después de invocar la función: -21-
+
</source>
+
===Funciones anónimas===
+
<br />
+
{{MRM_Pregunta|Title=Qué son|
+
;Son funciones que no tienen nombre
+
;Se conocen como (funciones de clousura funciones cierre), y de hecho implementa la clase (Clousura)[https://www.php.net/manual/es/class.closure.php]
+
;Crear una función anónima:
+
<source lang=php>
+
function (){
+
return "Hola desde una función anónima";
+
}
+
 
+
}}
+
</source>
+
<br />
+
{{MRM_Pregunta|
+
;Ahora viene la paradoja de para qué puede servir y cómo la puedo invocar.
+
}}
+
<br />
+
;Para invocar  a una función anónima tenemos dos formas:
+
:<span id=r>A través de las variables de  funciones</span>
+
:<span id=r>Como argumento en una función</span>, o sea que el parámetro de una función sea otra función
+
;Variables de funciones
+
*Declaro una variable y le asigno una función
+
*En realidad es una forma diferente de declarar la función e invocarla, tiene la ventaja de gestionar todo como variables (posible comodidad por parte del programador)
+
*Si uso esta técnica, no puedo invocar a la función antes de su declaración (ya que no existe en contenido de la variable)
+
*Consiste en declarar una variable y asiganer la función
+
*Posteriormente podré invocar la función a través de la variable (he de poner también paréntesis en la invocación y no olvidar el ; (punto y coma) en la asignación)
+
<source lang=php>
+
<?php
+
$mi_funcion = function () {
+
return "hola caracola";
+
};
+
d
+
echo $mi_funcion();
+
//imprimiría "hola caracola"
+
//=====================================
+
 
+
echo $mi_funcion();
+
 
+
$mi_funcion = function () {
+
return "hola caracola";
+
};
+
//Este código fallaría,
+
//=====================================
+
<?php
+
echo mi_funcion();
+
 
+
function mi_funcion () {
+
return "hola caracola";
+
};
+
 
+
//Este código funcionaría, php legunaje de doble pasada en su interpretación,
+
?>
+
 
+
</source>
+
 
+
 
+
 
+
<source lang=php>
+
 
+
</source>
+
;Invocación usando la función como un parámetro en otra función
+
*Esto se puede conseguir ver, usando alguna función del sistema que espere recibir una función de clausura, como iremos viendo a lo largo del curso.
+
spl_autoload_register(https://www.php.net/manual/es/function.spl-autoload-register.php)
+
array_walk (https://www.php.net/manual/es/function.array-walk.php)
+
array_map (https://www.php.net/manual/es/function.array-map.php)
+
array_reduce (https://www.php.net/manual/es/function.array-reduce.php)
+
 
+
*Otra forma de utilizarlo, es usando la función <span id=r>call_user_func</span>, con esta función invocamos a una función anónima, necesitamos acceder a ello, y lo podemos hacer a través de un identificador, o escribiendo el código de la funćión anónima
+
<source lang=php>
+
<?php
+
call_user_func(function ($nombre){echo "hola $nombre";}, "Manuel");
+
 
+
//Este código nos escribirá "hola Manuel";
+
?>
+
</source>
+
*Podríamos implementar el código anterior usando variables, posiblemente se puede considerar que  mejoraríamos en legibilidad
+
<source lang=php>
+
<?php
+
$saludar = function ($nombre){
+
echo "hola $nombre";
+
};
+
 
+
call_user_func($saludar, "Manuel");
+
 
+
?>
+
</source>
+
 
+
===Funciones flecha===
+
*Las funciones flecha es una forma más corta de escribir funciones anónimas simples
+
Aparece en php en la versión 7.4
+
*Limitaciones de funciones flecha.
+
#
+
 
</div>
 
</div>

Última revisión de 19:14 5 nov 2024


Funciones


Icon objectives.jpg
Objetivo
Las funciones son un elemento fundamental
  • Permiten crear código modular.
  • Ayudan a estructurar el programa de manera ordenada.

Declaración de funciones

// Declarar una función
function nombre_de_funcion([tipo_de_parametro] $parametro_formal[=valor_por_defecto], ...)[: tipo_retorno]
{
    ...
    [return ...];
}
 
// Llamar
nombre_de_funcion($parametro_real);
  • Es importante diferenciar entre **declarar** una función e **invocar** una función.
  • Aunque parece obvio, es un punto importante.
  • En la declaración de una función, tenemos tres partes:
Nombre o identificación de la función
Parámetros formales
  • Se especifican entre paréntesis. (Los paréntesis son necesarios, aunque no haya parámetros).
  • Se puede especificar el tipo de cada parámetro (a partir de la versión 7.2).
  • Se puede asignar un valor por defecto (si un parámetro tiene valor por defecto, no es obligatorio proporcionarle un valor en la invocación).
Tipo de retorno
Es opcional.
  1. El cuerpo de la función. Dentro de él puede estar la instrucción `return`, la cual finaliza la ejecución de la función y devuelve el flujo al programa, a la instrucción que llamó a la función.
  2. `return` puede (o debe) devolver el valor que queremos que la función retorne.
Identificador de función
  • El nombre de la función es un identificador que empieza por una letra o guion bajo, seguido de 0 o más letras, números o guiones bajos.
Icon present.gif
Tip: Expresión regular para el identificador de funciones:
[a-zA-Z_f_][a-zA-Z0-9_]*


Parámetros formales
  • Son nombres de variables que usaremos al escribir el código o cuerpo de la función.
  • El nombre debe ser significativo y se convertirán en variables locales a la función.
  • Al finalizar la función, estas variables se eliminan de la memoria.


Icon key points.gif

Parámetros formales

Los parámetros formales son variables locales a la función.

Proceso de creación / invocación de una función

Primero, declaramos la función
  • Esto implica reservar una zona de memoria identificada con el nombre de la función.
  • El contenido de esas posiciones de memoria será el conjunto de acciones de la función.
  • Estas acciones estarán definidas en función de los **parámetros formales** de la declaración.

Declaracion funcion.png

Invocación de la función
  • La invocación es una instrucción para ejecutar la función.

Invocacion funcion 1.png

  • Lo primero que ocurre es que el programa accede a esa zona de memoria.

Invocacion funcion 2.png

  • Luego, se asignan los valores reales de la invocación a los parámetros formales de la función.

Invocacion funcion 3.png

  • Cuando la función termina de ejecutarse, se retorna a la instrucción que sigue a la llamada.
  • Si la función devuelve un valor, este se asigna a la variable de la instrucción de asignación desde la cual se invocó.


Icon activity.jpg
Ejercicio usando funciones

Escribe un programa en el que en el programa principal se declaren dos variables, $a y $b.

  • Crea una función que reciba como parámetros locales $a y $b,
  • La función debe visualizar el valor de las variables, modificarlas, y volver a visualizarlas.
  • En el programa principal:
  1. Asigna valor a las variables.
  2. Visualízalas.
  3. Invoca la función.
  4. Visualiza de nuevo las variables.



  • Una posible solución
    <?php
       function a($a, $b){
           echo "Dentro de la función visualizando valores <hr />";
           echo "Valor de los parámetros \$a = $a \$b = $b <br />";
           $a += 5;
           $b += 5;
           echo "Valor de los parámetros \$a = $a \$b = $b <br />";
           echo "Salgo de la función";
       }
       //Programa principal
       $a = 100;
       $b = 200;
       echo "En el main antes de invocar la función visualizando variables<hr />";
       echo "Valor de variables \$a = $a \$b = $b <br />";
       a($a, $b);
       echo "En el main después de invocar la función visualizando variables<hr />";
       echo "Valor de variables \$a = $a \$b = $b <br />";
?>

Parámetros formales: Valores y referencias

  • Como hemos visto, los parámetros formales reciben valores pasados en la invocación de la función.
  • Si queremos que la función pueda modificar el valor de los parámetros, debemos pasarlos **por referencia**.
  • Esto permite que se pase la dirección de memoria donde se guarda el valor, en lugar del valor en sí.
  • En PHP no podemos visualizar ni operar con la dirección de memoria, ya que no existe la aritmética de punteros.
Parámetros formales
Valores y referencias

Para pasar el parámetro por referencia, simplemente coloca el símbolo & antes del nombre de la variable en la declaración de los parámetros:

function nombre_funcion(&$paramRef1, &$paramRef2, $paramVal1){
   ...
}


Icon activity.jpg
Ejercicio usando funciones y parámetros

Escribe un programa donde en el programa principal se declaren tres variables: $a, $b y $c.

  • Crea una función que reciba como parámetros &$num1, &$num2 y $num3.
  • La función debe visualizar el valor de las variables, modificarlas, y volver a visualizarlas.
  • En el programa principal:
  1. Asigna valor a las variables.
  2. Visualízalas.
  3. Invoca la función.
  4. Visualiza de nuevo las variables.



  <?php
       function a(&$num1, &$num2, $num3){
           echo "Dentro de la función visualizando valores <hr />";
           echo "Valor de los parámetros \$num1 = $num1 \$num2 = $num2 \$num3 = $num3<br />";
           $num1 += 5;
           $num2 += 5;
           $num3 += 5;
 
           echo "Valor de los parámetros \$num1 = $num1 \$num2 = $num2 \$num3 = $num3<br />";
           echo "Salgo de la función";
       }
       //Programa principal
       $a = 100;
       $b = 200;
       $c = 300;
       echo "En el main antes de invocar la función visualizando variables<hr />";
       echo "Valor de variables \$a = $a \$b = $b \$c = $c <br />";
       a($a, $b, $c);
       echo "En el main después de invocar la función visualizando variables<hr />";
       echo "Valor de variables \$a = $a \$b = $b \$c = $c <br />";
?>
Invocando funciones
  • Una vez creada una función, se puede invocar como si fuera una instrucción.
  • No sin razón, en ciertos contextos se refiere a funciones como "instrucciones virtuales".
  • En PHP, puedes invocar una función antes de declararla, siempre que esté en el mismo archivo.



Icon casestudy.gif
Ejemplo de invocación de funciones
Icon present.gif
Tip: Este código funcionará correctamente


    <?php
      a(5, 6);  
      /*Más instrucciones*/
      function a($a, $b){
          echo "Valor de $a";
          echo "Valor de $b";
      }




Icon casestudy.gif
Ejemplo de invocación de funciones
Icon present.gif
Tip: Este código no funcionará


<?php
      a(5, 6);  
      /*Más instrucciones*/
      include ("funciones.php");
?>
  • Contenido del archivo funciones.php
<?php
function a($a, $b){
          echo "Valor de $a";
          echo "Valor de $b";
}
?>


Variables dentro de una función

  • Dentro de una función, las variables que declaremos son **locales** a esa función.
  • No se puede acceder a su valor fuera de la función.
  • Esto también implica que dentro de una función no se puede acceder al valor de una variable definida fuera de la función.
  • Observa el siguiente ejemplo:
<?php
 
function modifica_valor(){
    echo "Valor de <b>var1</b> dentro de la función: -$var1- <br />";
    $var1++;
    echo "Valor de <b>var1</b> dentro de la función, modificado: -$var1- <br />";
}
 
$var1 = 20;
 
echo "Valor de <b>var1</b> en el programa principal antes de invocar la función: -$var1- <br />";
modifica_valor();
echo "Valor de <b>var1</b> en el programa principal después de invocar la función: -$var1- <br />";
?>
  • Genera la siguiente salida:
Valor de var1 en el programa principal antes de invocar la función: -20- 
Valor de var1 dentro de la función: -- 
Valor de var1 dentro de la función, modificado: -1- 
Valor de var1 en el programa principal después de invocar la función: -20-
  • Si queremos acceder al valor de $var1 dentro de la función, podemos usar la palabra reservada global:
<?php
 
function modifica_valor(){
    global $var1; // Indicamos que esta variable se puede usar globalmente.
    echo "Valor de <b>var1</b> dentro de la función: -$var1- <br />";
    $var1++;
    echo "Valor de <b>var1</b> dentro de la función, modificado: -$var1- <br />";
}
 
$var1 = 20;
 
echo "Valor de <b>var1</b> en el programa principal antes de invocar la función: -$var1- <br />";
modifica_valor();
echo "Valor de <b>var1</b> en el programa principal después de invocar la función: -$var1- <br />";
?>
  • Ahora, observamos que el valor dentro de la función se puede acceder y modificar.
Valor de var1 en el programa principal antes de invocar la función: -20- 
Valor de var1 dentro de la función: -20- 
Valor de var1 dentro de la función, modificado: -21- 
Valor de var1 en el programa principal después de invocar la función: -21-

Funciones recursivas

  • Al igual que en otros lenguajes de programación, en PHP el uso de funciones recursivas es una opción muy interesante cuando necesitamos obtener valores que dependen de cálculos repetitivos sobre sí mismos
  • Claros ejemplos son casos de factoriales, secuencias de Fibonacci, o procesamiento de estructuras de datos jerárquicas (por ejemplo, árboles o directorios anidados).



Icon define.gif
¿Qué es una Función Recursiva?

Una función recursiva es aquella que se llama a sí misma para resolver un problema que puede dividirse en subproblemas más pequeños y de la misma naturaleza.


  • La idea principal es que la función continúe llamándose a sí misma, resolviendo cada vez una parte más pequeña del problema, hasta que alcanza una condición base que detiene las llamadas recursivas.
Ejemplo de Factorial con Recursividad

El cálculo del factorial de un número n es un ejemplo clásico de recursividad. El factorial de n (representado como n!) se calcula multiplicando n por el factorial de n - 1 hasta llegar a 1. En términos matemáticos:

𝑛!=𝑛 × (𝑛−1) × (𝑛−2)×...× 1

Podemos implementar esto en PHP usando una función recursiva:

function factorial($num) {
    return $num <= 1 ? 1 : $num * factorial($num - 1);
}
echo factorial(5); // Salida: 120
  • Analicemos este caso
  1. La condición base es cuando num es igual a 1, devolviendo 1 y deteniendo la recursión.
  2. Si num es mayor que 1, la función llama a factorial de nuevo con el valor num - 1, multiplicándolo por num.

Ventajas y Desventajas de la Recursión

Ventajas
  • Código más limpio y legible: Las soluciones recursivas suelen ser más compactas y fáciles de entender que sus equivalentes iterativas.
  • Ideal para problemas jerárquicos: La recursión es muy útil para trabajar con datos que tienen una estructura de árbol o jerárquica, como explorar directorios o manejar datos de tipo árbol (DOM, menús anidados, etc.).
Desventajas
  • Consumo de memoria: Cada llamada recursiva agrega un nuevo nivel al stack de llamadas de PHP, lo cual puede llevar a un error de desbordamiento si la recursión es profunda o si no se define correctamente la condición base.
  • Complejidad de depuración: Las funciones recursivas pueden ser más difíciles de depurar debido a la cantidad de llamadas anidadas que se realizan.

Consideraciones Importantes al Usar Recursividad en PHP

  • Podríamos generalizar para cualquier lenguaje de programación
Establecer una condición base clara
    • Sin una condición base, la función entrará en un ciclo infinito de llamadas hasta que se agote la memoria.
Evaluar el caso iterativo
    • A veces, una solución iterativa (usando bucles) puede ser más eficiente y evitar problemas de memoria.
Controlar la profundidad
    • PHP establece un límite en la profundidad de recursión por defecto (generalmente 100 o 1000 niveles), aunque este límite puede configurarse. Sin embargo, es importante considerar la eficiencia y el consumo de memoria.

Funciones Anónimas




Icon define.gif
¿Qué son?
Son funciones que no tienen nombre.
También se conocen como funciones de clausura o funciones cierre. En PHP, las funciones anónimas implementan la clase `Closure` ([documentación de Closure](https://www.php.net/manual/es/class.closure.php)).
Para crear una función anónima en PHP, se usa la siguiente estructura
function () {
    return "Hola desde una función anónima";
};




Icon qmark.gif
Pregunta
Puede parecer paradójico, pero ¿para qué sirve una función anónima y cómo podemos invocarla?



En PHP, existen dos formas principales de invocar una función anónima
1. A través de variables de función.
2. Como argumento en otra función. Es decir, pasamos la función anónima como parámetro a otra función.

Variables de Función

  • En PHP, podemos asignar una función anónima a una variable y luego invocar la función a través de esa variable. Esta técnica permite trabajar con funciones de forma similar a las variables, lo que puede ser cómodo en ciertos casos.
  • Usar variables de función requiere tener presente que no podemos invocar la función antes de la asignación, ya que hasta ese punto, la función no existe en la variable.
  • Para asignar una función anónima a una variable, simplemente declaramos la variable y le asignamos la función. Para invocarla, solo tenemos que llamar a la variable como si fuera una función, usando paréntesis `()`.
<?php
$mi_funcion = function () {
    return "hola caracola";
};
 
echo $mi_funcion(); // Imprime: hola caracola
?>
  • Si intentamos invocar la función antes de asignarla a la variable, obtendremos un error.*
// Error: La función no existe antes de la asignación
echo $mi_funcion();
 
$mi_funcion = function () {
    return "hola caracola";
};

Comparación con Funciones Nombradas

En cambio, si usáramos una función nombrada en lugar de una función anónima, PHP podría procesarla sin importar el orden, debido a su interpretación en dos pasadas:

<?php
echo mi_funcion(); // Esto funcionará debido a la doble pasada de PHP
 
function mi_funcion() {
    return "hola caracola";
}
?>

Pasar Funciones Anónimas como Parámetros en Otras Funciones

  • Otra manera de usar funciones anónimas es pasarlas como parámetros en otras funciones. En PHP, hay varias funciones del sistema que aceptan una función de clausura como argumento. Al usar funciones anónimas en estos casos, podemos crear lógica personalizada que se ejecuta en el contexto de la función de nivel superior.

Algunos ejemplos de funciones del sistema que aceptan funciones de clausura como argumentos son: - [`spl_autoload_register`](https://www.php.net/manual/es/function.spl-autoload-register.php) - [`array_walk`](https://www.php.net/manual/es/function.array-walk.php) - [`array_map`](https://www.php.net/manual/es/function.array-map.php) - [`array_reduce`](https://www.php.net/manual/es/function.array-reduce.php)

Uso de `call_user_func` para Invocar Funciones Anónimas

  • Otra forma de invocar una función anónima es mediante la función `call_user_func`. Esta función acepta una función anónima como primer argumento y, opcionalmente, otros argumentos que serán pasados a la función anónima.
<?php
call_user_func(function ($nombre) {
    echo "Hola $nombre";
}, "Manuel");
// Este código imprimirá: Hola Manuel
?>

Mejorar la Legibilidad Usando Variables

  • En lugar de escribir la función anónima directamente en call_user_func, podemos asignarla a una variable para mejorar la legibilidad del código.
<?php
$saludar = function ($nombre) {
    echo "Hola $nombre";
};
 
call_user_func($saludar, "Manuel");
// Este código imprimirá: Hola Manuel
?>

Acceso a Variables del Entorno: `use` vs. `global`

  • Cuando trabajamos con funciones anónimas en PHP, hay una característica importante sobre cómo acceder a las variables del entorno.
  • En PHP, las funciones anónimas no tienen acceso directo a las variables del entorno en el que se crean.
  • Si necesitamos usar esas variables dentro de la función anónima, tenemos dos opciones: usar `use` o declarar las variables como `global`.

Uso de `use` para Capturar Variables del Entorno

  • El operador `use` permite capturar variables del entorno en el momento en que se define la función anónima.
  • Esto es útil cuando queremos hacer referencia a valores específicos del entorno externo sin modificarlos (o incluso, modificarlos en algunos casos específicos).
  • `use` permite pasar variables del entorno a la función anónima por valor, aunque también es posible pasarlas por referencia si se indica con `&`.
  • Cuando usamos `use`, la variable queda "capturada" en el estado en el que estaba al momento de declarar la función anónima.
Ejemplo con `use`
$mensaje = "Hola";
 
$mi_funcion = function() use ($mensaje) {
    echo $mensaje;
};
 
$mi_funcion(); // Imprime: Hola
  • En este ejemplo, '$mensaje se pasa a la función anónima con use y puede ser utilizada dentro de la función.
  • Sin embargo, cualquier cambio en $mensaje dentro de la función no afectará a la variable $mensaje fuera de la función a menos que la pasemos por referencia.
  • Para modificar la variable del entorno, podemos hacerlo pasando la variable por referencia con use (&$variable):
$contador = 1;
 
$incrementar = function() use (&$contador) {
    $contador++;
};
 
$incrementar();
echo $contador; // Imprime: 2
  • En este ejemplo, $contador se pasa por referencia a la función anónima, por lo que cualquier modificación dentro de la función afectará también al valor de $contador fuera de ella.

Funciones Flecha

Las funciones flecha (o arrow functions) se introdujeron en PHP 7.4 como una forma compacta y conveniente de escribir funciones anónimas.

  • Son especialmente útiles cuando necesitamos una función rápida, generalmente en una línea, y son comunes en funciones de callback o como argumentos en otras funciones.
  • Sin embargo, tienen ciertas limitaciones en comparación con las funciones anónimas tradicionales.

Sintaxis de las Funciones Flecha

La sintaxis de una función flecha es más breve que la de una función anónima tradicional. La estructura básica es la siguiente:

$variable = fn() => expresion;
  • O con parámetros
$variable = fn($parametro) => expresion_con_parametro;
  • Ejemplo:
$mi_funcion = fn($parametro) => $parametro * 2;

- La palabra clave fn indica el inicio de la función flecha. - Los parámetros se colocan entre paréntesis. - La flecha `=>` separa los parámetros del cuerpo de la función. - Solo se permite una expresión en el cuerpo de la función, cuyo valor se retorna automáticamente.

Limitaciones de las Funciones Flecha

  • Aunque las funciones flecha ofrecen una sintaxis más concisa, tienen ciertas limitaciones:
  • 1. Solo permiten una única expresión: Las funciones flecha solo pueden contener una sola expresión. Esto significa que no pueden tener múltiples líneas de código ni declaraciones complejas.
  • 2. No pueden usarse de forma recursiva: Al no permitir referencia a sí mismas, no es posible implementar recursión con funciones flecha. Si necesitas recursión, deberás usar una función anónima tradicional o una función nombrada.
  • 3. Limitaciones en el uso de `use`: En funciones anónimas, es común usar `use` para capturar variables del entorno en el momento de la definición de la función.
    • Sin embargo, en las funciones flecha, use no es necesario, ya que heredan automáticamente las variables del ámbito externo.
    • A diferencia de las funciones anónimas, no es posible personalizar qué variables se capturan ni controlar si se pasan por referencia o por valor.
    • Las funciones flecha siempre heredan las variables por valor.
    • Esto significa que, si necesitas modificar una variable del entorno dentro de la función flecha, no puedes hacerlo directamente. Para lograr este efecto, deberías usar una función anónima y pasar la variable por referencia con `use (&$variable)`.

4. Sin acceso a `$this` fuera de objetos: Aunque las funciones flecha heredan el valor de `$this` cuando se utilizan dentro de un objeto, no pueden acceder a `$this` si no están dentro del contexto de un objeto.

Ejemplos de Uso de Funciones Flecha

$factor = 3;
 
// Función flecha que hereda $factor del entorno
$multiplicar = fn($num) => $num * $factor;
 
echo $multiplicar(5); // Salida: 15
  • En este ejemplo, la función flecha accede a la variable `$factor` desde el ámbito en el que fue definida. No necesitamos `use`, ya que la variable es heredada automáticamente.
  • Si intentáramos modificar `$factor` dentro de la función, no afectaría el valor de `$factor` en el ámbito externo:
$factor = 3;
 
$incrementar = fn($num) => $factor += $num;
 
echo $incrementar(2); // Salida: 5 (modificado solo dentro de la función)
echo $factor;         // Salida: 3 (sin cambios en el entorno externo)
  • Para realizar este tipo de modificación en el ámbito externo, se debe usar una función anónima en lugar de una función flecha:
$factor = 3;
 
$incrementar = function($num) use (&$factor) {
    $factor += $num;
};
 
$incrementar(2);
echo $factor; // Salida: 5 (modificado en el ámbito externo)


Icon summary.gif
Resumen sobre fn()=>expresion

Las funciones flecha en PHP son útiles para simplificar el código en situaciones en las que necesitamos una función rápida y sencilla, especialmente como callback o dentro de funciones de una sola línea. Sin embargo, debido a sus limitaciones (como la imposibilidad de usar `use` para pasar variables específicas por referencia o de forma selectiva), se debe de evaluar cuándo es más apropiado usar una función anónima en lugar de una función flecha.