Así que podemos contar letras, sumar números y ponerlos en la pantalla. El siguiente paso es hacerlo con más gente, para comparar el peso de Garikoitz con el de Agurtzane Mendikozelaia Agirrebeitia. ¿Quién es más pesado?
<?php
// primero Garikoitz
$garikoitz = "Garikoitz Subijana Lertxundi";
$pesoDeGarikoitz = 0;
for ($i = 0; $i < strlen($garikoitz); $i++) {
$pesoDeGarikoitz = $pesoDeGarikoitz + ord($garikoitz[$i]);
}
echo $garikoitz . ' pesa ' . $pesoDeGarikoitz . ' kg.';
// y ahora Agurtzane
$agurtzane = "Agurtzane Mendikozelaia Agirrebeitia";
$pesoDeAgurtzane = 0;
for ($i = 0; $i < strlen($agurtzane); $i++) {
$pesoDeAgurtzane = $pesoDeAgurtzane + ord($agurtzane[$i]);
}
echo $agurtzane . ' pesa ' . $pesoDeAgurtzane . ' kg.';Esto no es buena práctica, por motivos obvios. Estamos comparando a dos personas, pero ¿qué pasa cuando tengamos diez? No podemos copiar y pegar el mismo código cada vez que queramos añadir una persona. ¡Necesitamos una función!
Segunda mano
Cuando escribimos programas nos encontramos con pequeños problemas que tenemos que nresolver una y otra vez,
y pronto nos cansaremos de repetir el mismo trozo de código una y otra vez. Por suerte, podemos extraer
las partes comunes de un trozo de código, ponerlas en lugar común, y simplemente hacer referencia a ese
lugar común cuando queramos realizar la operación de nuevo. En nuestro caso, el bucle for y la sentencia
echo son idénticas en ambas secciones del programa: lo único que cambia es el nombre de cada persona.
Vamos a crear una función: un bloque de código que puede recibir datos, realiza una serie de operaciones (probablemte usando esos datos que ha recibido) y devuelve (opcionalmente) un valor. Las funciones reciben nombres distintos en distintos lenguages de programación. En C/C++, PHP JavaScript o Python se llaman simplemente funciones, pero en Java sólo existen métodos, en Lisp además de funciones hay expresiones lambda, Pascal y Delphi tienen también procedimiento y otros programas tiene subrutinas. La idea siempre es la misma: reutilizar código para no escribir siempre lo mismo, reduciendo el tamaño del programa y la probabilidad de cometer errores.
Redundantemente
Si miramos el código de arriba de nuevo podemos ver que $garikoitz y $agurtzane, las variables, tienen el
mismo papel (almacenar el nombre de la persona), al igual que $pesoDeGarikoitz y $pesoDeAgurtzane (almacenar el
peso total). Empecemos por homogeneizar un poco el código, reemplazando el nombre de las variables que almacenan
el nombre y el peso pero con otras iguales para ambas secciones:
<?php
// primero Garikoitz
$nombre = "Garikoitz Subijana Lertxundi";
$peso = 0;
for ($i = 0; $i < strlen($nombre); $i++) {
$peso = $peso + ord($nombre[$i]);
}
echo $nombre . ' pesa ' . $peso . ' kg.';
// y ahora Agurtzane
$nombre = "Agurtzane Mendikozelaia Agirrebeitia";
$peso = 0;
for ($i = 0; $i < strlen($nombre); $i++) {
$peso = $peso + ord($nombre[$i]);
}
echo $nombre . ' pesa ' . $peso . ' kg.';Ahora las dos secciones del programa, para ambas personas, sólo difieren en el valor de la variable $nombre.
Estamos listos para crear una función que contenga en resto del programa:
<?php
// nuestra función
function peso()
{
$peso = 0;
for ($i = 0; $i < strlen($nombre); $i++) {
$peso = $peso + ord($nombre[$i]);
}
echo $nombre . ' pesa ' . $peso . ' kg.';
}
// primero Garikoitz
$nombre = "Garikoitz Subijana Lertxundi";
// y ahora Agurtzane
$nombre = "Agurtzane Mendikozelaia Agirrebeitia";Ahora mismo este programa no hace nada, porque el código que ponemos dentro de las funciones no se
ejecuta mientras no llamemos a la función. En nuestro caso, tenemos que llamar a peso() dos veces:
<?php
// nuestra función
function peso()
{
$peso = 0;
for ($i = 0; $i < strlen($nombre); $i++) {
$peso = $peso + ord($nombre[$i]);
}
echo $nombre . ' pesa ' . $peso . ' kg.';
}
// primero Garikoitz
$nombre = "Garikoitz Subijana Lertxundi";
peso();
// y ahora Agurtzane
$nombre = "Agurtzane Mendikozelaia Agirrebeitia";
peso();Pero esto todavía no es suficiente; dentro de la función peso() estamos usando la variable $nombre, pero
las funciones tienen su propio ámbito, lo que significa que no saben qué sucede a su alrededor. La variable
$nombre está definida fuera de la función peso(), y por lo tanto no podemos usarla dentro. Literalmente,
peso() no tiene ni idea de quiénes son Garikoitz y Agurtzane.
La mejor forma de decirle a peso() que calcule el peso de una persona es diciéndole quién es la persona.
Las funciones aceptan parámetros de entrada, que se pueden pasar a la función poniéndolos dentro de los
paréntesis que se usan en la llamada.
<?php
// nuestra función
function peso()
{
$peso = 0;
for ($i = 0; $i < strlen($nombre); $i++) {
$peso = $peso + ord($nombre[$i]);
}
echo $nombre . ' pesa ' . $peso . ' kg.';
}
// primero Garikoitz
$nombre = "Garikoitz Subijana Lertxundi";
peso($nombre);
// y ahora Agurtzane
$nombre = "Agurtzane Mendikozelaia Agirrebeitia";
peso($nombre);Peeeeeeero eso aún no arregla el programa. Cuando definimos la función, tenemos que especificar los parámetros que acepta:
<?php
// nuestra función
function peso($nombre)
{
$peso = 0;
for ($i = 0; $i < strlen($nombre); $i++) {
$peso = $peso + ord($nombre[$i]);
}
echo $nombre . ' pesa ' . $peso . ' kg.';
}
// primero Garikoitz
$nombre = "Garikoitz Subijana Lertxundi";
peso($nombre);
// y ahora Agurtzane
$nombre = "Agurtzane Mendikozelaia Agirrebeitia";
peso($nombre);Ten en cuenta que llamar a las variables de abajo $nombre y al parámetro de la función también $nombre no
es necesario. Lo que importa en realidad es el orden de los parámetros:
<?php
// nuestra función
function f($primero, $segundo)
{
echo $primero . ' ' . $segundo;
}
$mi_nombre = "Koldobika";
$mis_apellidos = "Guridi Elkorobarrutia";
f($mi_nombre, $mis_apellidos);En este ejemplo, cuando llamamos a la función f() le pasamos el valor de $mi_nombre primero y el de
$mis_apellidos después. En la definición de la función hemos declarado dos argumentos, $primero y $segundo.
Cuando la función es llamada, el primer parámetro, $primero, recibe el valor de $mi_nombre, y el segundo parámetro,
$segundo, recibe el valor de $mis_apellidos.
Lo mismo ocurre con la funciópn peso() y el parámetro $nombre: cada vez que llamemos a peso(), su parámetro
$nombre va a almacenar el valor de la variable $nombre que usamos en la llamada, va a ejecutar el bucle
for usando ese valor, y va a imprimir el nombre de la persona y su peso:
Valores de retonno
Estoy pensando que nuestra función peso(), a pesar de ser pequeña, hace demasiado: calcula el peso y lo imprime.
Es lógico pensar que no siempre vamos a querer imprimir el peso, o igual lo queremos imprimir de otra forma. Es
muy importante limitar las responsabilidades de las funciones que creemos, porque las funciones que hacen muchas
cosas tienen a producir problemas más adelante, cuando nuestro programa evoluciona.
Si tenemos una función llamada peso(), probablemente queremos que calcule el peso y nada más. Ya nos encargamos
nosotros de imprimirlo, si es necesario. O podemos crear otra función que lo imprima, si vemos que estamos
imprimiendo pesos continuamente, como los cárteles de la droga.
<?php
// nuestra función
function peso($nombre)
{
$peso = 0;
for ($i = 0; $i < strlen($nombre); $i++) {
$peso = $peso + ord($nombre[$i]);
}
return $peso;
}
// primero Garikoitz
$pesoDeGarikoitz = peso("Garikoitz Subijana Lertxundi");
// y ahora Agurtzane
$pesoDeAgurtzane = peso("Agurtzane Mendikozelaia Agirrebeitia");Dentro de la función podemos usar el comando return para que la función devuelva un valor. A la hora de la llamada,
podemos usar la función como si fuese un valor, y asignarlo a variables. Ahora tenemos el peso de ambas
personas en dos variables, y podemos imprimir ambos valores a nuestra manera:
He eliminado, de paso, las variables
$nombre, porque eran supérfluas.
echo "Garikoitz pesa " . $pesoDeGarikoitz . " y Agurtzane pesa " . $pesoDeAgurtzane.Jo, da gloria verlo.