Una función es una sección de código que contiene un conjunto de instrucciones, donde las instrucciones describen cómo se debe realizar una tarea en particular. Las funciones se declaran y luego se pueden llamar una o más veces. Declarar una función implica especificar las instrucciones que contendrá la función. Cuando se llama a una función, ejecuta esas instrucciones. Las funciones son fundamentales para la programación de computadoras en general y juegan un papel central en JS++.
Nota: este tutorial no cubre las funciones externas en JS++. Una función externa se declara con la function
palabra clave y devuelve un tipo externo. Examinaremos las funciones externas y los tipos externos en el Capítulo 9. (Para obtener una vista previa, un tipo externo es uno que no es un tipo JS++; por lo general, estos serán tipos JavaScript). Este tutorial examina las funciones internas de JS++. Las funciones internas no se declaran con la function
palabra clave y pueden devolver cualquier tipo.
Declarar y llamar funciones
Antes de que podamos usar una función para hacer algo, debemos declararla. Entonces, comencemos por ver cómo se declaran las funciones. Cree una nueva carpeta y asígnele el nombre «Funciones». Luego cree un nuevo archivo y asígnele el nombre «Functions.jspp». Escribe el siguiente código:
external $; string getFavoriteAnimalString(string animal) { return "My favorite animal is the " + animal; }
Guarde Functions.jspp en su carpeta Funciones. El código que hemos escrito declara una función llamada getFavoriteAnimalString
. Este nombre es apropiado, porque el propósito de la función es devolver una string que indica el animal favorito de uno. Esa tarea se lleva a cabo mediante la declaración de retorno en el cuerpo de la función (la parte dentro de las llaves): la declaración de retorno evalúa la expresión a la derecha de la return
palabra clave y luego envía la expresión evaluada de vuelta a la persona que llama a la función (donde podría estar asignado a una variable, por ejemplo). Dado que el propósito de getFavoriteAnimalString
es devolver una string, podemos decir que el tipo de retorno de la función es string
y lo especificamos escribiendo string
a la izquierda del nombre de la función.
Así como la salida de getFavoriteAnimalString
será una string, también toma una entrada de string . Para componer la string que informa sobre el animal favorito, la función necesita saber qué animal en particular es el favorito. Recibe esta información de entrada a través del parámetro de string llamado animal
, que escribimos entre paréntesis a la derecha del nombre de la función. Cuando en una etapa posterior de nuestro programa llamemos getFavoriteAnimalString
para que se ejecute, pasaremos una string en particular a su parámetro de entrada: la string en particular que le pasemos será el argumento de la función .
Nota: La distinción entre los parámetros de una función y sus argumentos puede resultar confusa. Para aclarar, un parámetro es una variable escrita al declarar una función. El tipo de parámetro especifica qué tipo de entrada toma la función. Un argumento, por el contrario, es el valor real que se pasa a una función como entrada cuando se llama a la función. El argumento se convierte en el valor de la variable de parámetro.
Antes getFavoriteAnimalString
de llamar, configuremos un documento HTML que usaremos para mostrar el resultado. Cree un segundo archivo llamado «Funciones.html» y escriba lo siguiente:
<!DOCTYPE html> <title>Functions program</title> <body> <p id="content"></p> <script src="http://code.jquery.com/jquery-1.12.4.min.js"></script> <script src="Functions.jspp.js"></script> </body> </html>
Guarde Functions.html en su carpeta Funciones. Ahora regrese a Functions.jspp y escriba lo siguiente, debajo del código donde declaró getFavoriteAnimalString
:
string favoriteAnimalString = getFavoriteAnimalString("cat"); $("#content").text(favoriteAnimalString);
En la primera de estas nuevas líneas, llamamos getFavoriteAnimalString
, pasándole la string «gato» como argumento. Esta llamada de función devuelve la string «Mi animal favorito es el gato», y asignamos esta string a la variable favoriteAnimalString
. En la segunda línea, usamos jQuery para seleccionar el elemento de «contenido» de Functions.html y establecer su texto en el valor de favoriteAnimalString
. Compile Functions.jspp y luego abra Functions.html en un navegador. Si todo ha funcionado, su documento debería mostrar «Mi animal favorito es el gato».
Volviendo de una función
En nuestro ejemplo, getFavoriteAnimalString
devuelve una string. Sin embargo, en general, una función JS++ puede devolver cualquier tipo válido, siempre que el valor devuelto pertenezca al tipo de devolución especificado a la izquierda del nombre de la función en la declaración.
Una función no puede tener más de un tipo de devolución, pero no necesita devolver nada en absoluto. Si una función no devuelve nada, debe declararse con la void
palabra clave:
void displayFavoriteAnimalString(string animal) { string favoriteAnimalString = "My favorite animal is the " + animal; $("#content").text(favoriteAnimalString); }
Una void
función se puede declarar sin usar una declaración de retorno (como en el ejemplo anterior), o se puede declarar con la declaración return
; que no evalúa ni devuelve ninguna expresión.
Cuando una función ejecuta una declaración de retorno, sale inmediatamente. Esto significa que cualquier código escrito después de una declaración de devolución no se ejecutará.
Parámetros
Las funciones pueden tomar cero, uno o múltiples parámetros. Si una función toma múltiples parámetros, entonces esos parámetros pueden ser del mismo tipo o de diferentes tipos:
void displayFavoriteAnimalIfLucky(string animal, int number) { string favoriteAnimalString = "My favorite animal is the " + animal; if(number == 7){ $("#content").text(favoriteAnimalString); } }
Nota: una función también puede tomar un parámetro variádico , lo que permite que la función tome una cantidad infinita de argumentos para ese único parámetro. Sin embargo, una comprensión completa de los parámetros variadicos requiere una comprensión de las arrays, que no se cubrirá hasta el próximo tutorial. Por lo tanto, pospondremos la discusión de los parámetros variadicos hasta entonces.
funciones recursivas
Una función recursiva es aquella que puede llamarse a sí misma durante su ejecución. Aquí hay un ejemplo bien conocido de una función recursiva:
int factorial (int input) { if (input <= 1) { return input; } else { return input * factorial(input - 1); } }
El propósito de factorial
es calcular y devolver el factorial del input
parámetro. Por ejemplo, si llamamos factorial
con un input
5, devolverá 120.
factorial
ilustra una estructura general que es común a muchas funciones recursivas. La función maneja dos tipos de casos de manera diferente, según el valor del argumento de entrada. En el caso base , el valor del argumento significa que la tarea de la función se puede realizar fácilmente, con poco o ningún trabajo adicional requerido. Por lo tanto, la función regresa sin necesidad de llamarse a sí misma. En el caso recursivo , por el contrario, se requiere un trabajo adicional significativo. Para lograr esto, la función de alguna manera simplifica o reduce ese trabajo adicional, que implica llamarse a sí misma con un valor de entrada modificado. El valor de entrada modificado estará más cerca del valor necesario para calificar para un caso base.
El caso base para factorial
viene cuando el input
argumento es menor o igual que 1. En este caso, la función simplemente devuelve input
. Si input
es mayor que 1, por el contrario, la función devuelve input * factorial(input - 1)
. Así factorial
se llamará repetidamente a sí mismo, con el valor de input
disminuir en 1 con cada llamada recursiva. Cuando factorial
se llama a sí mismo con un input
valor de 1, esa llamada recursiva en particular regresa, lo que luego permite que regresen cada una de las llamadas recursivas anteriores.
Las funciones recursivas deben usarse con cuidado. En particular, es importante asegurarse de que con cada llamada recursiva, el valor del argumento de entrada se acerque más al necesario para el caso base. Si no hace esto, existe el peligro de que pueda crear una recurrencia infinita: esto provocará un error de tiempo de ejecución. Además, suele ser más eficaz utilizar una función iterativa (es decir, una que utilice un bucle) en lugar de una recursión. Cuando hay un beneficio en el uso de la recursividad, generalmente consiste en hacer que el código sea más fácil de leer, en lugar de aumentar la eficiencia computacional.
Sobrecarga
JS++ permite sobrecargar funciones . La sobrecarga consiste en declarar dos funciones con el mismo nombre, pero con listas de parámetros diferentes. Por ejemplo, podríamos sobrecargar una función llamada displayFavoriteAnimalString
de la siguiente manera:
void displayFavoriteAnimalString(string animal) {
string favoriteAnimalString = “Mi animal favorito es el ” + animal;
$(“#contenido”).texto(stringanimalfavorita);
}
void mostrarStringAnimalFavorito(string primerAnimal, string segundoAnimal) {
string stringAnimalFavorito = “Mis animales favoritos incluyen el ” + primerAnimal + ” y el ” + segundoAnimal;
$(“#contenido”).texto(stringanimalfavorita);
}
El compilador le permite declarar dos funciones con el mismo nombre de esta manera, debido a la diferencia en sus listas de parámetros: la primera función toma un solo parámetro de string, mientras que la segunda función toma dos. Esta diferencia significa que cuando llama a una de las dos funciones, no hay ambigüedad en cuanto a lo que significa: si proporciona un argumento de string, entonces debe ser la primera función, y si proporciona dos argumentos de string, entonces debe ser el segundo .
En el ejemplo dado, las dos funciones sobrecargadas tienen el mismo tipo de retorno: nulo. Sin embargo, esto no es obligatorio. Siempre que las funciones sobrecargadas tengan diferentes listas de parámetros, sus tipos de retorno pueden ser iguales o diferentes. Sin embargo, no puede sobrecargar las funciones con las mismas listas de parámetros y diferentes tipos de devolución: esto generaría ambigüedad sobre qué función se refería a la persona que llama, por lo que el compilador no lo permitirá.
La sobrecarga puede tener sentido cuando las funciones sobrecargadas realizan roles conceptualmente similares, donde esta similitud debería ser obvia desde la perspectiva de la persona que llama. La sobrecarga no debe usarse cuando las funciones sobrecargadas desempeñan funciones conceptualmente diferentes, ya que esto hará que su código sea más difícil de entender. Una técnica particular que se debe evitar, si es posible, es dar a las funciones sobrecargadas diferentes tipos de devolución: esto no se considera un buen estilo de codificación.
Callbacks y expresiones de función
Considere el siguiente código:
external $; int(int, int) processNumbers = int(int a, int b) { return a + b; };
Si observa detenidamente esta sintaxis (¡y toma nota del punto y coma final!), verá que no es la sintaxis normal de una declaración de función. Más bien, lo que tenemos aquí es una asignación variable. La variable se llama processNumbers
y su tipo se especifica mediante el código a la izquierda del nombre: int(int, int)
. Este es un tipo de devolución de llamada . Una variable de este tipo puede tomar como valor una función. Sin embargo, el rango de funciones que puede tomar la variable está restringido a aquellas cuyos parámetros y tipo de devolución coincidan con los especificados por el tipo de devolución de llamada. Entonces, dado que processNumbers
tiene el tipo de devolución de llamada int(int, int)
, se puede asignar una función processNumbers
solo si toma dos int
parámetros y devuelve un int
.
El código a la derecha del signo “=” asigna una expresión de función a los números de proceso. Una expresión de función se diferencia de una declaración de función en que se evalúa como un valor (la función expresada). Esto significa que una expresión de función puede usarse (como aquí) en una asignación de variable, o pasarse como argumento a otra función, o devolverse desde otra función.
La función asignada a processNumbers
es una función de suma. Suma los dos int
argumentos y devuelve el resultado. La asignación está bien, ya que la función de suma tiene los parámetros y el tipo de retorno especificado por el tipo de devolución de llamada de la variable: toma dos int
parámetros y devuelve un int
. Ahora podemos llamar processNumbers
:
int result = processNumbers(3, 4); $("#content").text(result);
Sin embargo, más adelante en nuestro programa, podríamos decidir asignar una función diferente a processNumbers
:
processNumbers = int(int a, int b) { return a * b; };
Esta asignación es tan válida como la anterior, ya que la función de multiplicación asignada también tiene los parámetros correctos y el tipo de retorno: toma dos int
parámetros y devuelve un int
. Si llamamos processNumbers
después de asignarle esta nueva función, el resultado será diferente del devuelto por nuestra llamada anterior.
Publicación traducida automáticamente
Artículo escrito por CharlesKozenyPelling y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA