¿Qué son los parámetros variádicos?
ObjectScript permite definir métodos que aceptan un número variable de argumentos usando la sintaxis `args...`. En lugar de fijar cuántos parámetros recibe un método, dejas que el llamante decida cuántos enviar.
Se pueden invocar de dos formas:
1. Con argumentos individuales: `metodo(val1, val2, val3)`
2. Expandiendo un array: `metodo(args...)`
Crea tus propios métodos variádicos
Puedes definir un método con un parámetro fijo y un número variable de extras:
ClassMethod MiMetodo(fijo As %String, extras...) As %Status
{
Write "Parámetro fijo: ", fijo, !
Write "Número de extras: ", $Get(extras, 0), !
For i = 1:1:$Get(extras, 0) {
Write " Extra ", i, ": ", extras(i), !
}
Quit $$$OK
}
Y llamarlo de cualquiera de estas dos formas:
// Forma 1: Argumentos individuales
Do ##class(MiClase).MiMetodo("hola", "valor1", "valor2")
// Forma 2: Expandiendo un array
Set params = 2
Set params(1) = "valor1"
Set params(2) = "valor2"
Do ##class(MiClase).MiMetodo("hola", params...)
// Ambas producen la misma salida:
// Parámetro fijo: hola
// Número de extras: 2
// Extra 1: valor1
// Extra 2: valor2
La convención del array
El array que se pasa con `args...` sigue una convención simple de ObjectScript:
- `args` contiene el número de elementos
- `args(1)`, `args(2)`, etc. contienen los valores
Esto significa que estas dos llamadas son equivalentes:
// Forma 1: Argumentos individuales
Set result = statement.%Execute("Juan", 25, "Barcelona")
// Forma 2: Expandiendo un array
Set args = 3
Set args(1) = "Juan"
Set args(2) = 25
Set args(3) = "Barcelona"
Set result = statement.%Execute(args...)
La segunda forma es la que nos interesa: podemos construir el array dinámicamente y expandirlo en la llamada.
Aplicación práctica: SQL dinámico seguro
Construir consultas SQL dinámicas concatenando strings es tentador... y peligroso:
// ⚠️ NO HAGAS ESTO - Vulnerable a SQL Injection
Set sql = "SELECT * FROM Paciente WHERE Nombre LIKE '%" _ nombre _ "%'"
La forma correcta es usar `%SQL.Statement` con parámetros `?`. Pero, ¿qué pasa cuando no sabes cuántos parámetros tendrás hasta el momento de ejecución?
Aquí es donde los variádicos brillan. El método `%Execute()` está definido así:
Method %Execute(%parm...) As %SQL.StatementResult
Acepta parámetros variádicos, así que podemos construir nuestro array dinámicamente y expandirlo:
Implementación completa
ClassMethod BuscarPacientes(filtrosJSON As %DynamicObject) As %SQL.StatementResult
{
Set sql = "SELECT ID, Nombre, Edad, Ciudad FROM Paciente WHERE 1=1"
// Construir condiciones y argumentos dinámicamente
Set args = 0 // args será nuestro array variádico
Set iterator = filtrosJSON.%GetIterator()
While iterator.%GetNext(.key, .value) {
If key = "nombre" {
Set sql = sql _ " AND Nombre LIKE ?"
Set args($Increment(args)) = "%" _ value _ "%"
} ElseIf key = "edad" {
Set sql = sql _ " AND Edad = ?"
Set args($Increment(args)) = value
} ElseIf key = "ciudad" {
Set sql = sql _ " AND Ciudad = ?"
Set args($Increment(args)) = value
}
}
// Preparar el statement
Set statement = ##class(%SQL.Statement).%New()
Set status = statement.%Prepare(sql)
If $$$ISERR(status) { Quit $$$NULLOREF }
// ¡La magia! Expandir el array como argumentos variádicos
Quit statement.%Execute(args...)
}
Ejemplo de uso
// Filtros dinámicos desde un JSON
Set filtros = {"nombre": "Juan", "ciudad": "Barcelona"}
Set resultado = ##class(MiPaquete.Utilidades).BuscarPacientes(filtros)
While resultado.%Next() {
Write resultado.%Get("Nombre"), " - ", resultado.%Get("Ciudad"), !
}
No importa si recibes 1, 5 o 20 filtros: el mismo código los maneja de forma segura.
Conclusión
Los parámetros variádicos con `args...` te permiten:
- Construir arrays de argumentos dinámicamente
- Expandirlos al llamar cualquier método que los soporte
- Evitar SQL injection usando parámetros preparados
- Eliminar cadenas interminables de `If`/`ElseIf`