2011-05-16 47 views
70

En el wiki de Lua he encontrado una manera de definir valores por defecto para los argumentos que faltan:Definir valores por defecto para los argumentos de la función

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

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

Respuesta

62

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

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

(Esto se ve en muchos lugares en Lua, como the advanced forms of LuaSocket's protocol modules y constructores en . IUPLua)

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

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 f desaparecidos La tabla de parámetros se tomará de la tabla __index en su metatabla (ver the documentation on metatables).

Por supuesto, es posible utilizar estilos de parámetros más avanzados utilizando constructores de tablas y funciones; puede escribir lo que necesite. Por ejemplo, here es una función que construye una función que toma tablas de argumentos nominales o posicionales de una tabla que define los nombres de parámetros y valores predeterminados y una función que toma una lista de argumentos regulares.

Como una característica no a nivel de lenguaje, este tipo de llamadas se pueden cambiar para proporcionar nuevos comportamientos y semántica:

  • variables se podrían hacer para aceptar más de un nombre
  • las variables de posición y de palabras clave variables pueden intercalar - y que define tanto puede dar preferencia a cualquiera de los dos (o causar un error)
  • palabra clave de sólo las variables sin posición se pueden realizar, así como sin nombre de sólo posición de las unidades
  • La construcción mesa bastante-verbosa podría hacerse analizando como Tring
  • La lista de argumentos se podría utilizar textualmente si la función se llama con algo distinto de 1 mesa

Algunas funciones útiles para la escritura de traductores argumento se unpack (que se mueve a table.unpack en 5.2), setfenv (en desuso en 5.2 con la nueva construcción _ENV) y select (que devuelve un único valor de una lista de argumentos dada, o la longitud de la lista con '#').

+0

A Acabo de empezar 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

+1

En la mayoría de los casos, mantenerlo simple es el camino a seguir. Las interfaces de metaparámetros solo son realmente necesarias para objetos con una gran cantidad de atributos opcionales (como objetos UI). –

+0

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

44

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

+6

Esta respuesta es completamente refutada por la respuesta de Stuart P. Bentley a continuación, en el que la función es llamada con un constructor de tablas. Esta es una de las fortalezas de Lua: si bien no tiene un montón de lujos, los elementos fundamentales de Lua te permiten hacer cosas ilimitadas, realmente destacables por el tamaño pequeño y la simplicidad del lenguaje. –

17

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

+1

Si no está buscando 'false', una forma más sencilla es colocar primero la variable y la última predeterminada. 'b = b or 7' – Rebs

+1

Dado que OP mencionó que en su pregunta, pensé que sería superfluo mencionar (la pregunta era sobre formas de definir variables predeterminadas * que no sean *' b = b o 7'). –

5

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() 
Cuestiones relacionadas