En matemáticas y en programación informática , una función variádica es una función de aridad indefinida , es decir, una que acepta un número variable de argumentos . La compatibilidad con funciones variádicas varía considerablemente entre los lenguajes de programación .
Descripción general
Existen numerosas operaciones matemáticas y lógicas que se presentan de forma natural como funciones variádicas. Por ejemplo, la suma de números o la concatenación de cadenas u otras secuencias son operaciones que pueden considerarse aplicables a cualquier número de operandos (aunque formalmente en estos casos se aplique la propiedad asociativa ).
Otra operación que se ha implementado como función variádica en muchos lenguajes es el formato de salida. La función de Cprintf y la función de Common Lispformat son dos ejemplos de ello. Ambas toman un argumento que especifica el formato de la salida y cualquier número de argumentos que proporcionan los valores que se van a formatear.
Las funciones variádicas pueden exponer problemas de seguridad de tipos en algunos lenguajes. Por ejemplo, en C printf, si se usa sin precaución, puede dar lugar a una clase de vulnerabilidades conocidas como ataques de formato de cadena . El ataque es posible porque la compatibilidad del lenguaje con las funciones variádicas no es segura en cuanto a tipos: permite que la función intente extraer más argumentos de la pila de los que se colocaron allí, corrompiendo la pila y provocando un comportamiento inesperado. Como consecuencia de esto, el Centro de Coordinación CERT considera que las funciones variádicas en C representan un riesgo de seguridad de alta gravedad. [ 1 ]
En los lenguajes de programación funcional , las funciones variádicas pueden considerarse complementarias a la función apply , que toma una función y una lista/secuencia/matriz como argumentos, y llama a la función con los argumentos proporcionados en esa lista, pasando así un número variable de argumentos a la función. En el lenguaje funcional Haskell , las funciones variádicas pueden implementarse devolviendo un valor de una clase de tipo ; si las instancias de son un valor de retorno final y una función , esto permite cualquier número de argumentos adicionales .TTr(T t) => x -> tx
Un tema relacionado en la investigación de reescritura de términos se denomina "hedges" o variables de cobertura . [ 2 ] A diferencia de las variádicas, que son funciones con argumentos, las hedges son secuencias de argumentos en sí mismas. También pueden tener restricciones ("no tomar más de 4 argumentos", por ejemplo) hasta el punto de que no son de longitud variable (como "tomar exactamente 4 argumentos"), por lo que llamarlas variádicas puede ser engañoso. Sin embargo, se refieren al mismo fenómeno, y a veces la terminología es confusa, lo que da lugar a nombres como variable variádica (sinónimo de hendge). Nótese el doble significado de la palabra variable y la diferencia entre argumentos y variables en la programación funcional y la reescritura de términos. Por ejemplo, un término (función) puede tener tres variables, una de ellas una hendge, lo que permite que el término tome tres o más argumentos (o dos o más si se permite que la hendge esté vacía).
Ejemplos
do
Para implementar de forma portable funciones variádicas en el lenguaje C<stdarg.h> , se utiliza el archivo de cabecera estándar . El <varargs.h>archivo de cabecera anterior ha sido descontinuado en favor de <stdarg.h>. En C++, <cstdarg>se utiliza el archivo de cabecera. [ 3 ]
#include <stdarg.h> #include <stdio.h>doble promedio ( int count , ...) { va_list ap ; doble suma = 0 ;va_start ( ap , count ); // Antes de C23: Requiere el último parámetro fijo (para obtener la dirección) for ( int j = 0 ; j < count ; ++ j ) { sum += va_arg ( ap , int ); // Incrementa ap al siguiente argumento } va_end ( ap );devolver suma / recuento ; }int main ( int argc , char * argv []) { printf ( "%f \n " , average ( 3 , 1 , 2 , 3 )); return 0 ; }Esto calculará el promedio de un número arbitrario de argumentos. Tenga en cuenta que la función no conoce el número de argumentos ni sus tipos. La función anterior espera que los tipos sean inty que el número de argumentos se pase en el primer argumento (este es un uso frecuente, pero de ninguna manera impuesto por el lenguaje o el compilador). En algunos otros casos, por ejemplo printf , el número y los tipos de argumentos se determinan a partir de una cadena de formato. En ambos casos, esto depende de que el programador proporcione la información correcta. (Alternativamente, se puede usar un valor centinela como NULLo nullptrpara indicar el final de la lista de parámetros). Si se pasan menos argumentos de los que la función cree, o los tipos de argumentos son incorrectos, esto podría hacer que lea en áreas de memoria no válidas y puede conducir a vulnerabilidades como el ataque de cadena de formato . Dependiendo del sistema, incluso usar NULLcomo centinela puede encontrar tales problemas; nullptro se puede usar un puntero nulo dedicado del tipo de destino correcto para evitarlos.
stdarg.hdeclara un tipo, va_list, y define cuatro macros: va_start, va_arg, va_copy, y va_end. Cada invocación de va_starty va_copydebe ir acompañada de una invocación correspondiente de va_end. Al trabajar con argumentos variables, una función normalmente declara una variable de tipo va_list( apen el ejemplo) que será manipulada por las macros.
va_starttoma dos argumentos, unva_listobjeto y una referencia al último parámetro de la función (el que está antes de los puntos suspensivos; la macro usa esto para orientarse). En C23 , el segundo argumento ya no será necesario y las funciones variádicas ya no necesitarán un parámetro con nombre antes de los puntos suspensivos. [ nota 1 ] [ 5 ] Inicializa elva_listobjeto para su uso porva_argova_copy. El compilador normalmente emitirá una advertencia si la referencia es incorrecta (por ejemplo, una referencia a un parámetro diferente al último, o una referencia a un objeto completamente diferente), pero no impedirá que la compilación se complete normalmente.va_argRecibe dos argumentos: unva_listobjeto (previamente inicializado) y un descriptor de tipo. Se expande al siguiente argumento variable y tiene el tipo especificado. Las invocaciones sucesivasva_argpermiten procesar cada uno de los argumentos variables por turno. Se produce un comportamiento no especificado si el tipo es incorrecto o si no hay un siguiente argumento variable.va_endtoma un argumento, unva_listobjeto. Sirve para limpiar. Si alguien quisiera, por ejemplo, escanear los argumentos variables más de una vez, el programador volvería a inicializar suva_listobjeto invocandova_endy luegova_startnuevamente sobre él.va_copytoma dos argumentos, ambosva_listobjetos. Clona el segundo (que debe haber sido inicializado) en el primero. Volviendo al ejemplo de "escanear los argumentos de la variable más de una vez", esto podría lograrse invocandova_starten un primerova_list, luego usandova_copypara clonarlo en un segundova_list. Después de escanear los argumentos de la variable una primera vez conva_argy el primerova_list(descartándolo conva_end), el programador podría escanear los argumentos de la variable una segunda vez conva_argy el segundova_list.va_endTambién debe llamarse en el clonadova_listantes de que la función contenedora retorne.
DO#
C# describe las funciones variádicas mediante la paramspalabra clave `variádica`. Se debe especificar un tipo para los argumentos, aunque ` object[]variádica` puede usarse como comodín. En el punto de llamada, se pueden enumerar los argumentos uno por uno o pasar un array preexistente con el tipo de elemento requerido. El uso de la forma variádica es una simplificación sintáctica de esta última opción.
espacio de nombres Wikipedia.Ejemplos ;usando el sistema ;public class Program { static int Foo ( int a , int b , params int [] args ) { // Devuelve la suma de los enteros en args, ignorando a y b. int sum = 0 ; foreach ( int i in args ) { sum += i ; } return sum ; } static void Main ( string [] args ) { Console . WriteLine ( Foo ( 1 , 2 )); // 0 Console . WriteLine ( Foo ( 1 , 2 , 3 , 10 , 20 )); // 33 int [] manyValues = [ 13 , 14 , 15 ]; Console . WriteLine ( Foo ( 1 , 2 , manyValues )); // 42 } }C++
La funcionalidad básica de funciones variádicas en C++ es prácticamente idéntica a la de C. Antes de C++26 , se podía omitir la coma antes de los puntos suspensivos. C++ también permite funciones variádicas sin parámetros con nombre (por ejemplo, void f(...);). Sin embargo, hasta C++26 no existía una forma portable de acceder a esos argumentos, ya que va_startrequería el nombre del último parámetro fijo de la función. Desde C++26, C++ adopta la forma de un argumento de va_start, que coincide con C23 y permite acceder a los argumentos incluso cuando la función no tiene parámetros fijos.
Las plantillas variádicas (paquetes de parámetros) también se pueden usar en C++ con expresiones de plegado integradas en el lenguaje . Las plantillas variádicas son la única forma segura de tener funciones/parámetros variádicos en C++, ya que C++ carece de parámetros variádicos sin plantilla al estilo de Java.
importar std ;plantilla < typename ... Ts > void fooPrint ( Ts ... args ) { (( std :: print ( "{} " , args )), ...); }int main ( int argc , char * argv []) { fooPrint ( 1 , 3.14f ); // 1 3.14 fooPrint ( "Foo" , 'b' , true , nullptr ); // Foo b true nullptr }Los estándares de codificación CERT para C++ prefieren encarecidamente el uso de plantillas variádicas (paquetes de parámetros) en C++ en lugar de la función variádica al estilo C debido a un menor riesgo de uso indebido. [ 6 ] Las plantillas variádicas son la única forma de lograr parámetros variádicos con seguridad de tipos al estilo Java.
Para restringir el parámetro a ser solo de tipo T(similar a T... args) en Java, se puede usar el concepto std::same_as[ 7 ] o std::convertible_to(para tipos que pueden estar destinados a ser convertibles). [ 8 ]
usando std :: same_as ;// Equivalente a la declaración de Java // <T> void fn(T... args) template < typename T > void fn ( same_as < T > auto ... args ) { // ... }Carbón
Carbon , un lenguaje diseñado teniendo en cuenta la interoperabilidad con C++, ofrece variádicas, en particular expansiones de paquetes. [ 9 ]
// Toma un número arbitrario de vectores con tipos de elementos arbitrarios y // devuelve un vector de tuplas donde el i-ésimo elemento del vector es // una tupla de los i-ésimos elementos de los vectores de entrada. fn Zip [ ... each ElementType :! type ]( ... each vector : Vector ( each ElementType )) -> Vector (( ... each ElementType )) { ... var each iter : auto = each vector . Begin (); var result : Vector (( ... each ElementType )); while ( ... and each iter != each vector . End ()) { result . push_back (( ... each iter )); ... each iter ++ ; } return result ; }Fortran
Desde la revisión Fortran 90, las funciones o subrutinas de Fortran pueden aceptar argumentos opcionales: [ 10 ] la lista de argumentos sigue siendo fija, pero aquellos que tienen el optionalatributo pueden omitirse en la llamada a la función/subrutina. La función intrínseca present()puede utilizarse para detectar la presencia de un argumento opcional. Los argumentos opcionales pueden aparecer en cualquier lugar de la lista de argumentos.
prueba de programa implícita ningunareal :: x !> se pasan todos los argumentos: call foo ( 1 , 2 , 3.0 , 4 , x ) !< produce 1 \ 2 \ 3.0 \ 4 \ 6.0 (la "\" denota un salto de línea) !> se omiten los últimos 2 argumentos: call foo ( 1 , 2 , 3.0 ) !< produce 1 \ 2 \ 3.0 !> se omiten el segundo y el cuarto argumento: los argumentos que se colocan después de !> un argumento omitido debe pasarse con una palabra clave: call foo ( 1 , c = 3.0 , e = x ) !< produce 1 \ 3.0 \ 6.0 !> alternativamente, la revisión Fortran 2023 ha introducido el .NIL. pseudoconstante !> para denotar una llamada de argumento omitido foo ( 1 , . NIL ., 3.0 , . NIL ., x ) !< produce 1 \ 3.0 \ 6.0contiene!> La subrutina foo() tiene 2 argumentos obligatorios y 3 opcionales. Subrutina foo ( a , b , c , d , e ) entero , intención ( entrada ) :: a entero , intención ( entrada ), opcional :: b real , intención ( entrada ) :: c entero , intención ( entrada ), opcional :: d real , intención ( salida ), opcional :: e imprimir * , a si ( presente ( b )) imprimir * , b imprimir * , c si ( presente ( d )) imprimir * , d si ( presente ( e )) entonces e = 2 * c imprimir * , c fin si fin de la subrutinafin del programaIr
Las funciones variádicas en Go pueden ser llamadas con cualquier número de argumentos finales. [ 11 ]fmt.Println es una función variádica común; utiliza una interfaz vacía como un tipo comodín.
paquete principalimportar "fmt"// Esta función variádica toma un número arbitrario de enteros como argumentos. func sum ( nums ... int ) { fmt . Print ( "La suma de " , nums ) // También es una función variádica. total := 0 for _ , num := range nums { total += num } fmt . Println ( " es " , total ) // También es una función variádica. }func main () { // Las funciones variádicas se pueden llamar de la forma habitual con argumentos individuales. sum ( 1 , 2 ) // "La suma de [1 2] es 3" sum ( 1 , 2 , 3 ) // "La suma de [1 2 3] es 6"// Si ya tienes varios argumentos en una porción, aplícalos a una función variádica // usando func(slice...) de esta manera. nums := [] int { 1 , 2 , 3 , 4 } sum ( nums ... ) // "La suma de [1 2 3 4] es 10" }Producción:
La suma de [1 2] es 3 La suma de [1 2 3] es 6 La suma de [1 2 3 4] es 10
Java
Al igual que en C#, el Objecttipo en Java está disponible como un comodín.
En Java, un parámetro puede ser variádico usando la notación de puntos suspensivos. Esto es esencialmente equivalente a un array, pero no requiere ser envuelto como tal. Por ejemplo, String... argsy String[] argsserían prácticamente idénticos.
paquete org.wikipedia.examples ;public class Program { // Los métodos variádicos almacenan cualquier argumento adicional que reciban en un array. // En consecuencia, `printArgs` es en realidad un método con un parámetro: un // array de longitud variable de `String`s. private static void printArgs ( String ... strings ) { for ( String s : strings ) { System . out . println ( s ); } }public static void main ( String [] args ) { printArgs ( "hello" ); // abreviatura de printArgs(new String[] {"hello"}) printArgs ( "hello" , "world" ); // abreviatura de printArgs(new String[] {"hello", "world"}) } }JavaScript
JavaScript no tiene en cuenta los tipos de argumentos variables. El argumento variable se denota con ..., que denota un "parámetro rest" que recopila los argumentos en un array.
función suma (... números ) { return números . reduce (( a , b ) => a + b , 0 ); }console.log ( sum ( 1 , 2 , 3 ) ); // 6 console.log ( sum ( 3 , 2 ) ); // 5 console.log ( sum ( ) ) ; // 0También es posible crear una función variádica utilizando el objeto de argumentos, aunque solo se puede usar con funciones creadas con la functionpalabra clave.
función suma () { return Array . prototype . reduce . call ( arguments , ( a , b ) => a + b , 0 ); }console.log ( sum ( 1 , 2 , 3 ) ); // 6 console.log ( sum ( 3 , 2 ) ); // 5 console.log ( sum ( ) ) ; // 0Tenga en cuenta que en TypeScript , debido a que el parámetro rest es una matriz, esto se denota de la siguiente manera:
función suma ( ...números : número []) : número { return números . reduce (( a , b ) => a + b , 0 ); }TypeScript también permite forzar que el parámetro rest tenga un número exacto de elementos (es decir, una tupla):
// Fuerza exactamente tres números function sumExactlyThree (... numbers : [ number , number , number ]) : number { return numbers . reduce (( a , b ) => a + b , 0 ); }// Fuerza al menos dos números function sumAtLeastTwo (... números : [ número , número , ... número []]) : número { return números . reduce (( a , b ) => a + b , 0 ); }// Fuerza a que el primer argumento sea una cadena, luego todo lo que venga después de la función log (... args : [ cadena , ... cualquier []]) { // ... }Lua
Las funciones de Lua pueden pasar argumentos variables a otras funciones de la misma manera que otros valores usando la returnpalabra clave. Las tablas se pueden pasar a funciones variádicas usando, en Lua versión 5.2 o superior [ 12 ]table.unpack , o Lua 5.1 o inferior [ 13 ]unpack . Los argumentos variables se pueden usar como una tabla construyendo una tabla con el argumento variable como valor.
función suma (...) --... designa argumentos variables local suma = 0 para _ , v en pares ({...}) hacer --crear una tabla con argumentos variables es lo mismo que crear una con valores estándar suma = suma + v fin devolver suma finvalores = { 1 , 2 , 3 , 4 } suma ( 5 , table.unpack ( valores )) --devuelve 15. table.unpack debe ir después de cualquier otro argumento, de lo contrario no todos los valores se pasarán a la función.función add5 (...) devuelve ... + 5 --esto es un uso incorrecto de argumentos variables y solo devolverá el primer valor proporcionado .entradas = {} función procesar_entradas () local procesado = {} para i , v en pares ( entradas ) hacer procesado [ i ] = v --código de procesamiento de marcador de posición fin devolver tabla.desempaquetar ( procesado ) --devuelve todas las entradas de una manera que se puede usar como un argumento variable finprint ( process_entries ()) --la función print toma todos los argumentos variables y los escribe en la salida estándar separados por saltos de línea.Pascal
Pascal está estandarizado por las normas ISO 7185 (“Pascal estándar”) y 10206 (“Pascal extendido”). Ninguna de las formas estandarizadas de Pascal admite rutinas variádicas, excepto ciertas rutinas integradas ( read/ readLny write/ writeLn, y adicionalmente en EPreadStr / writeStr).
No obstante, los dialectos de Pascal implementan mecanismos similares a las rutinas variádicas. Delphi define un tipo de dato que puede asociarse con el último parámetro formal . Dentro de la definición de la rutina, es un , una matriz de registros variantes . [ 14 ] El miembro del tipo de dato mencionado permite inspeccionar el tipo de dato del argumento y su posterior manejo adecuado. El compilador Free Pascal también admite las rutinas variádicas de Delphi. [ 15 ]arrayofconstarrayofconstarrayofTVarRecVTyperecord
Esta implementación, sin embargo, técnicamente requiere un único argumento, que es un array. Pascal impone la restricción de que los arreglos deben ser homogéneos. Este requisito se elude utilizando un registro variante. GNU Pascal define una especificación de parámetros formales variádicos reales usando puntos suspensivos ( ...), pero hasta 2022 no se ha definido ningún mecanismo portable para usar tal. [ 16 ]
Tanto GNU Pascal como FreePascal permiten que las funciones declaradas externamente utilicen una especificación de parámetros formales variádica mediante puntos suspensivos ( ...).
PHP
PHP no tiene en cuenta los tipos de argumentos variables a menos que el argumento esté tipado.
función suma ( ... $nums ) : int { return suma_array ( $nums ); }echo suma ( 1 , 2 , 3 ); // 6Y argumentos variádicos tipificados:
función suma ( int ... $nums ) : int { return suma_array ( $nums ); }echo sum ( 1 , "a" , 3 ); // TypeError: El argumento 2 pasado a sum() debe ser de tipo int (desde PHP 7.3)Pitón
A Python no le importan los tipos de argumentos variables.
from typing import Anydef foo ( a : Any , b : Any , * args : Any ]) -> None : print ( args ) # args es una tupla (secuencia inmutable).if __name__ == "__main__" : foo ( 1 , 2 ) # args = () foo ( 1 , 2 , 3 ) # arga = (3,) foo ( 1 , 2 , 3 , "hello" ) # args = (3, "hello")Los argumentos de palabra clave se pueden almacenar en un diccionario.
def bar ( * args : Any , ** kwargs : Any ]) -> Any : # cuerpo de la funciónTenga en cuenta que, aunque argstiene tipo , está anotado con [ 17 ] .tuple[Any,...]*argsAny
Raku
En Raku , el tipo de parámetros que crean funciones variádicas se conocen como parámetros de matriz slurpy y se clasifican en tres grupos:
Aplanado y baboso
Estos parámetros se declaran con un solo asterisco ( *) y aplanan los argumentos disolviendo una o más capas de elementos sobre los que se puede iterar (es decir, iterables ).
sub foo ( $a , $b , * @args ) { say @args . perl ; } foo ( 1 , 2 ) # [] foo ( 1 , 2 , 3 ) # [3] foo ( 1 , 2 , 3 , "hola" ) # [3 "hola"] foo ( 1 , 2 , 3 , [ 4 , 5 ], [ 6 ]); # [3, 4, 5, 6]sorbete sin aplanar
Estos parámetros se declaran con dos asteriscos ( **) y no aplanan ningún argumento iterable dentro de la lista, sino que mantienen los argumentos más o menos como están:
sub barra ( $a , $b , ** @args ) { decir @args . perl ; } barra ( 1 , 2 ); # [] barra ( 1 , 2 , 3 ); # [3] barra ( 1 , 2 , 3 , "hola" ); # [3 "hola"] barra ( 1 , 2 , 3 , [ 4 , 5 ], [ 6 ]); # [3, [4, 5], [6]]sorbo contextual
Estos parámetros se declaran con un +signo más (+) y aplican la " regla de argumento único " , que decide cómo manejar el argumento slurpy según el contexto. En pocas palabras, si solo se pasa un argumento y este es iterable, se utiliza para llenar el array de parámetros slurpy. En cualquier otro caso, +@funciona como **@(es decir, slurpy sin aplanar).
sub zaz ( $a , $b , + @args ) { say @args . perl ; } zaz ( 1 , 2 ); # [] zaz ( 1 , 2 , 3 ); # [3] zaz ( 1 , 2 , 3 , "hola" ); # [3 "hola"] zaz ( 1 , 2 , [ 4 , 5 ]); # [4, 5], un solo argumento llena el array zaz ( 1 , 2 , 3 , [ 4 , 5 ]); # [3, [4, 5]], comportándose como **@ zaz ( 1 , 2 , 3 , [ 4 , 5 ], [ 6 ]); # [3, [4, 5], [6]], comportándose como **@Rubí
A Ruby no le importan los tipos de argumentos variádicos.
def foo ( * args ) print args endfoo ( 1 ) # imprime `[1]=> nil`foo ( 1 , 2 ) # imprime `[1, 2]=> nil`Óxido
Rust no admite argumentos variables en las funciones. En su lugar, utiliza macros , que sí admiten argumentos variables. [ 18 ] Esta es esencialmente la razón por la que println!es una macro y no una función, ya que toma argumentos variables para formatear.
macro_rules! calcular { // El patrón para un solo `eval` ( eval $e : expr ) => {{ { let val : usize = $e ; // Forzar que los tipos sean enteros println! ( "{} = {}" , stringify! { $e }, val ); } }};// Descomponer múltiples `eval` recursivamente ( eval $e : expr , $( eval $es : expr ), + ) => {{ calculate ! { eval $e } calculate ! { $( eval $es ), + } }}; }fn main () { calcular ! { \ eval 1 + 2 , eval 3 + 4 , eval ( 2 * 3 ) + 1 } }Rust puede interactuar con el sistema variádico de C mediante un c_variadicinterruptor de características. Al igual que con otras interfaces de C, el sistema se considera unsafepara Rust y se marca con C linkage . [ 19 ] El parámetro variádico en sí se anota con , y la función puede marcarse si se garantiza que no accederá a sus argumentos variádicos. [ 20 ]...safe
#![característica(c_variadic)]pub unsafe extern "C" fn add ( n : usize , mut args : .. .) -> usize { let mut sum = 0 ; for _ in 0 .. n { sum += args . arg :: < usize > (); } sum }Scala
objeto Programa { // Los métodos variádicos almacenan cualquier argumento adicional que reciban en un array. // En consecuencia, `printArgs` es en realidad un método con un parámetro: un // array de longitud variable de `String`. private def printArgs ( strings : String * ): Unit = { strings . foreach ( println ) }def main ( args : Array [ String ]): Unit = { printArgs ( "hello" ); // abreviatura de printArgs(["hello"]) printArgs ( "hello" , "world" ); // abreviatura de printArgs(["hello", "world"]) } }Rápido
Swift tiene en cuenta el tipo de argumentos variádicos, pero el tipo genérico Anyestá disponible.
func greet ( timeOfTheDay : String , names : String ...) { // aquí, names es [String] print ( "Parece que tenemos \( names.count ) personas " ) for name in names { print ( "Hola \( name ) , buen \( timeOfTheDay ) " ) } }saludar ( horaDelDía : "mañana" , nombres : "Joseph" , "Clara" , "William" , "Maria" )// Salida: // Parece que tenemos 4 personas // Hola Joseph, buenos días // Hola Clara, buenos días // Hola William, buenos días // Hola Maria, buenos díasTcl
Un procedimiento o expresión lambda de Tcl es variádico cuando su último argumento es args: este contendrá una lista (posiblemente vacía) de todos los argumentos restantes. Este patrón es común en muchos otros métodos similares a procedimientos. [ 21 ] [ 22 ]
proc greet { timeOfTheDay args } { puts "Parece que tenemos [llength $args] personas"foreach name $args { puts "Hola $name, buen $timeOfTheDay" } }Saluda "Buenos días" "José" "Clara" "Guillermo" "María"# Salida: # Parece que tenemos 4 personas # Hola Joseph, buenos días # Hola Clara, buenos días # Hola William, buenos días # Hola Maria, buenos díasVéase también
Notas
- ↑ Era necesario hacer que el parámetro con nombre fuera opcional, ya que no había forma de especificar una función que aceptara un número indeterminado de argumentos en C23 tras la eliminación de las definiciones de funciones al estilo K&R. Dado que C++ ya utilizaba esta sintaxis con el mismo propósito, este cambio también sirvió para aumentar la compatibilidad entre los lenguajes. [ 4 ]
Referencias
- ↑ Klemens, Ben (2014). 21st Century C: C Tips from the New School . O'Reilly Media, Inc. p. 224. ISBN 978-1491904442.
- ↑ CLP (H): Programación lógica de restricciones para coberturas
- ↑ "<cstdarg> (stdarg.h) - Referencia de C++" . www.cplusplus.com . Archivado del original el 31/10/2012 . Consultado el 02/10/2007 .
- ↑ "C23 está terminado: esto es lo que hay en el menú §N2975 - Relajar los requisitos para las listas de parámetros variádicos" . 31 de julio de 2022.
- ↑ Gilding, Alex; Meneide, JeanHeyd (2022-04-15). "WG14-N2975 : Relajar los requisitos para las listas de parámetros variádicos, v3" (PDF) .
- ↑ "DCL50-CPP. No defina una función variádica al estilo C" .
- ↑ cppreference.com. "std::same_as" . cppreference.com . cppreference.com . Consultado el 17 de mayo de 2026 .
- ↑ cppreference.com. "std::convertible_to" . cppreference.com . cppreference.com . Consultado el 17 de mayo de 2026 .
- ↑ Proyecto de lenguaje Carbono (1 de abril de 2026). "Variadics - Documentación del lenguaje Carbono" . docs.carbon-lang.dev . Proyecto de lenguaje Carbono.
- ↑ "Argumentos opcionales" . Intel . Consultado el 18 de marzo de 2025 .
- ↑ "Aprende por ejemplo: funciones variádicas" .
- ↑ "Manual de referencia de Lua 5.2" . www.lua.org . Consultado el 5 de febrero de 2023 .
- ↑ "Manual de referencia de Lua 5.1" . www.lua.org . Consultado el 5 de febrero de 2023 .
- ↑ "Parámetros (Delphi)" . Consultado el 28 de agosto de 2023 .
- ↑ "Free Pascal - Guía de referencia" . Consultado el 28 de agosto de 2023 .
- ↑ "El manual de GNU Pascal" . Consultado el 28 de agosto de 2023 .
- ↑ "Anotación de *args y **kwargs - Tipado estático con Python" . typing.python.org . Consultado el 22 de mayo de 2026 .
- ↑ "Variadics" . Rust By Example .
- ↑ "2137-variádico" . El libro RFC de Rust .
- ↑ Los desarrolladores de Rust (25 de junio de 2026). "Bloques externos" . docs.rust-lang.org . Los desarrolladores de Rust.
- ↑ "Página del manual de procedimientos" . Documentación de Tcl/Tk .
- ↑ "args" . Wiki de Tcler .
Enlaces externos
- Función variádica . Tarea de Rosetta Code que muestra la implementación de funciones variádicas en más de 120 lenguajes de programación.
- Funciones con argumentos variables : un tutorial sobre funciones con argumentos variables para C++.
- Manual de GNU libc
- Subrutinas
- Comparación de lenguajes de programación