Definir valores predeterminados para argumentos de función

En la wiki de Lua encontré una forma de definir valores predeterminados para los argumentos faltantes:

function myfunction(a,b,c)
    b = b or 7
    c = c or 5
    print (a,b,c)
end

¿Es esa la única forma? El estilo PHP myfunction (a,b=7,c=5) no parece funcionar. No es que la forma Lua no funcione, solo me pregunto si esta es la única forma de hacerlo.

preguntado el 16 de mayo de 11 a las 19:05

6 Respuestas

Si desea argumentos con nombre y valores predeterminados como PHP o Python, puede llamar a su función con un constructor de tabla:

myfunction{a,b=3,c=2}

(Esto se ve en muchos lugares de Lua, como las formas avanzadas de los módulos de protocolo de LuaSocket y constructores en IUPLua.)

La función en sí podría tener una firma como esta:

function myfunction(t)
    setmetatable(t,{__index={b=7, c=5}})
    local a, b, c =
      t[1] or t.a, 
      t[2] or t.b,
      t[3] or t.c
    -- function continues down here...
end

Cualquier valor que falte en la tabla de parámetros se tomará del __index tabla en su metatabla (ver la documentación sobre metatablas).

Por supuesto, los estilos de parámetros más avanzados son posibles utilizando constructores de tablas y funciones; puede escribir lo que necesite. Por ejemplo, aquí es una función que construye una función que toma tablas de argumentos con nombre o posicionales de una tabla que define los nombres de los parámetros y los valores predeterminados y una función que toma una lista de argumentos regular.

Como característica que no es del nivel del idioma, estas llamadas se pueden cambiar para proporcionar nuevos comportamientos y semántica:

  • Se pueden hacer variables para aceptar más de un nombre
  • Las variables de posición y las variables de palabras clave se pueden intercalar, y la definición de ambas puede dar prioridad a cualquiera de las dos (o provocar un error)
  • Se pueden crear variables sin posición de solo palabras clave, así como variables de solo posición sin nombre
  • La construcción de la tabla bastante detallada se puede realizar analizando una cadena
  • La lista de argumentos podría usarse literalmente si la función se llama con algo que no sea 1 tabla

Algunas funciones útiles para escribir traductores de argumentos son unpack (moviéndose a table.unpack en 5.2), setfenv (obsoleto en 5.2 con el nuevo _ENV construcción y select (que devuelve un solo valor de una lista de argumentos dada, o la longitud de la lista con '#').

Respondido 21 Feb 14, 01:02

AI acaba de comenzar a usar lua. Lo mantendré simple por el momento, pero su publicación es muy informativa. Podría ser útil más adelante. Gracias. - ripat

En la mayoría de los casos, hacerlo sencillo es el camino a seguir. Las interfaces de metaparámetros solo son realmente necesarias para los objetos con una gran cantidad de atributos opcionales (como los objetos de la interfaz de usuario). - Stuart P. Bentley

Creo que esta respuesta es la que resuelve las preguntas, no la que actualmente está marcada como aceptada. Gracias por la iluminación :) - deshacer

Cabe señalar que la x or default La expresión que también se usa en esta respuesta no es realmente un verdadero equivalente a los valores predeterminados de los parámetros, sino solo una solución simplista que solo funciona si ambos nil y false son valores de parámetro no válidos. Digamos que el valor predeterminado de un parámetro booleano x is true y la persona que llama pasa un explícito false. entonces x or true da true, aunque false fue aprobado explícitamente. Una mejor versión sería if x == nil then x = default end, que también es más legible; todavía no puede manejar explícito nil aunque argumentos. - Jesper

¡Oh, oye, esta es la respuesta aceptada ahora! Lindo. (Para que conste, y para poner el comentario de @ Undo en contexto, la respuesta de jpjacobs a continuación fue la respuesta aceptada durante mucho tiempo: casi obtengo una segunda insignia populista encima de eso.) - Stuart P. Bentley

En mi opinión, no hay otra forma. Esa es solo la mentalidad de Lua: sin lujos y, excepto por un poco de azúcar sintáctico, sin formas redundantes de hacer cosas simples.

Respondido 11 Feb 14, 02:02

Esta respuesta está completamente refutada por la respuesta de Stuart P. Bentley a continuación, en la que la función se llama con un constructor de tabla. Este es uno de los puntos fuertes de Lua: si bien no tiene muchos adornos, los bloques de construcción fundamentales de Lua te permiten hacer cosas ilimitadas, realmente notables por el tamaño pequeño y la simplicidad del lenguaje. - Colin D. Bennett

@ColinDBennett Gracias por hablar: parece que el OP leyó su comentario y, en diciembre, cambió la respuesta aceptada en consecuencia. (Y ahora es la "respuesta de Stuart P. Bentley arriba", en aras de la claridad: guiño :) - Stuart P. Bentley

Técnicamente, hay b = b == nil and 7 or b (que debe utilizarse en el caso de false es un valor válido como false or 7 se evalúa como 7), pero probablemente eso no sea lo que estás buscando.

Respondido el 23 de enero de 14 a las 14:01

Si no está comprobando false, una forma más sencilla es poner la variable primero y la predeterminada al final. b = b or 7 - rebotes

Dado que el OP mencionó eso en su pregunta, pensé que sería superfluo mencionar (la pregunta era sobre formas de definir variables predeterminadas que no sea b = b or 7). - Stuart P. Bentley

La única forma que he encontrado hasta ahora que tiene sentido es hacer algo como esto:

function new(params)
  params = params or {}
  options = {
    name = "Object name"
  }

  for k,v in pairs(params) do options[k] = v end

  some_var = options.name
end

new({ name = "test" })
new()

Respondido 21 Abr '12, 04:04

Si su función no espera ningún booleano false ni nil para pasar como valores de parámetro, su enfoque sugerido está bien:

function test1(param)
  local default = 10
  param = param or default
  return param
end

--[[
test1(): [10]
test1(nil): [10]
test1(true): [true]
test1(false): [10]
]]

Si su función permite booleano false, Pero no nil, para pasar como valor de parámetro, puede comprobar la presencia de nil, como lo sugiere Stuart P. Bentley, siempre que el valor predeterminado no sea booleano false:

function test2(param)
  local default = 10
  param = (param == nil and default) or param
  return param
end

--[[
test2(): [10]
test2(nil): [10]
test2(true): [true]
test2(false): [false]
]]

El enfoque anterior se rompe cuando el valor predeterminado es booleano false:

function test3(param)
  local default = false
  param = (param == nil and default) or param
  return param
end

--[[
test3(): [nil]
test3(nil): [nil]
test3(true): [true]
test3(false): [false]
]]

Curiosamente, invertir el orden de las verificaciones condicionales permitir booleano false para ser el valor predeterminado, y es nominalmente más eficiente:

function test4(param)
  local default = false
  param = param or (param == nil and default)
  return param
end

--[[
test4(): [false]
test4(nil): [false]
test4(true): [true]
test4(false): [false]
]]

Este enfoque funciona por razones que parecen contrarias a la intuición hasta un examen más detenido, en el que se descubre que son bastante inteligentes.

Si desea parámetros predeterminados para funciones que do permitir nil valores que se pasen, deberá hacer algo aún más feo, como usar parámetros variadic:

function test5(...)
  local argN = select('#', ...)
  local default = false
  local param = default
  if argN > 0 then
    local args = {...}
    param = args[1]
  end
  return param
end

--[[
test5(): [false]
test5(nil): [nil]
test5(true): [true]
test5(false): [false]
]]

Por supuesto, los parámetros variadic frustran por completo el autocompletado y la vinculación de los parámetros de función en las funciones que los usan.

Respondido 04 Feb 21, 08:02

La respuesta corta es que es la mejor y más sencilla forma. en lua, las variables por defecto son iguales a nil . esto significa que si no pasamos el argumento a las funciones lua, el argumento es salidas pero es nil y los programadores lua utilizan este atributo lua para establecer el valor predeterminado.

tampoco es una forma de establecer el valor predeterminado, pero puede usar la siguiente función

esta función crea un error si no pasa valores a los argumentos

function myFn(arg1 , arg2)
err = arg1 and arg2
if not err then error("argument") end
-- or
if not arg1 and arg2 then error("msg") end

pero no es una buena manera y es mejor no usar esta función

y en los diagramas muestra un argumento opcional en [, arg]

function args(a1 [,a2])
-- some
end
function args ( a1 [,a2[,a3]])
-- some
end

Respondido 30 Abr '21, 19:04

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.