LUA:寻求有效且无差错的方法来分配默认参数

时间:2012-07-02 17:53:06

标签: lua

我没有在函数定义中使用长参数列表,而是更喜欢传递一些固定参数和一个“附加参数”表,如下所示:

function:doit( text, params )
end

这很好,因为它允许我稍后添加新的命名参数而不会破坏旧的调用。

当我尝试强制某些参数的默认值时,我遇到的问题出现了:

function:doit( text, params )
   local font     = params.font or native.systemBold 
   local fontSize = params.fontSize or 24
   local emboss   = params.emboss or true

   -- ...

end

以上代码在所有情况下都可以正常工作,除非我为浮雕传递'false':

doit( "Test text", { fontSize = 32, emboss = false } )

当我真的想要假的时候,上面的代码会导致浮雕设置为true。

要清楚,我想要的是将第一个非NIL值分配给浮雕,而不是我得到第一个非假和非NIL。

为了解决这个问题,我写了一小段代码来查找表中的第一个非NIL值并返回:

function firstNotNil( ... )
   for i = 1, #arg do
      local theArg = arg[i]
      if(theArg ~= nil) then return theArg end
   end
   return nil
end

使用这个函数,我会按如下方式重写浮雕赋值:

   local emboss   = firstNotNil(params.emboss, true)

现在,这肯定有效,但它似乎效率低下而且超过顶部。我希望有一种更紧凑的方式来做到这一点。

请注意:我发现这个红宝石结构看起来很有前途,我希望lua有类似的东西:

[c,b,a].detect { |i| i > 0 } -- Assign first non-zero in order: c,b,a

2 个答案:

答案 0 :(得分:8)

Lua的关系运算符计算其中一个操作数的值(即该值未被强制转换为boolean),因此您可以通过说a and b or c来获得C的三元运算符的等价物。在您的情况下,如果不是a,则要使用nil,否则使用ba == nil and b or a

local emboss = (params.emboss == nil) and true or params.emboss

不像以前那么漂亮,但你只需要为布尔参数做这件事。


  

[snip - Lua code]

     

现在,这肯定有效,但它似乎效率低下而且超出顶部。

     

请注意:我发现这个看起来很有前途的红宝石结构,我希望lua有   类似的东西:

     

[c,b,a] .detect {| i |我> 0} - 按顺序分配第一个非零:c,b,a

你的Lua功能不再过分或效率低下。根据源文本,Ruby构造更加简洁,但语义与firstNotNil(c,b,a)并没有太大区别。这两个构造最终都会创建一个列表对象,使用一组值对其进行初始化,然后通过线性搜索列表的函数运行它。

在Lua中,您可以使用带有select的vararg表达式跳过列表对象的创建:

function firstNotNil(...)
   for i = 1, select('#',...) do
      local theArg = select(i,...)
      if theArg ~= nil then return theArg end
   end
   return nil
end
  

我希望有一种更紧凑的方式来做到这一点。

关于唯一的方法是缩短功能名称。 ;)

答案 1 :(得分:4)

如果你真的想在一行中完成,你需要这样的东西,默认值为 true

local emboss   = params.emboss or (params.emboss == nil)

它不是很易读,但它有效。 (params.emboss == nil)当没有设置params.emboss时(当你需要一个默认值时),求值为true,否则为false。因此,当params.emboss为false时,该语句为false,如果为true,则该语句为true(true或false = true)。

对于默认值 false ,您最初尝试的方法可以使用:

local emboss   = params.emboss or false