Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using varargs in earlier version of Lua, but want compatibility with 5.2+

Tags:

lua

I'm currently coding for a Lightroom plugin. Lightroom does not use version 5.2. I have the following function, which works fine currently, but I am concerned as if Lightroom does upgrade to a newer version, this code will break. Do you have suggestions on providing varargs handling in this case in a lua version-independent manner?

The following code checks to see if the function F is used as a key in the table needsModule. If so, it composes a function that includes a call to change modules to the value pointed to by the key F followed by a call to function F and its arguments.

local function wrapFOM(F,...)
  local openModule = needsModule[F]
  if openModule == nil then
    return function() return F(unpack(arg)) end
  end
  return function()
    if LrApplicationView.getCurrentModuleName() ~= openModule then
      LrApplicationView.switchToModule(openModule)
    end
    return F(unpack(arg)) --proper tail call
  end
end
like image 998
rsjaffe Avatar asked Dec 19 '15 23:12

rsjaffe


2 Answers

Lua 5.1 and up support the new style of vararg handling:

function vfunc( ... )
  for i = 1, select( '#', ... ) do
    print( i, (select( i, ... )) )
  end
end

or if you really want the varargs in a newly allocated table each function call (beware of nil arguments):

function vfunc( ... )
  local args = {...}
  for i, v in ipairs( args ) do
    print( i, v )
  end
end

If you also need to support Lua 5.0, you are out of luck, because ... outside of a parameter list is a syntax error. You'd have to resort to conditional code generation to circumvent that:

-- newer Lua versions use load instead of loadstring
local loadstring = loadstring or load
-- feature test for Lua 5.1+
local supports_ellipsis = loadstring( "return ..." ) ~= nil
local args = supports_ellipsis and "{...}" or "arg"

function vararg( n, f )
  local t = {}
  for i = 1, n do t[ i ] = "_"..i end
  local params = table.concat( t, ", ", 1, n )
  local code = [[
return function( f )
  return function( ]]..params..[[, ... )
    return f( ]]..params..", "..args..[[ )
  end
end
]]
  return assert( loadstring( code, "=(vararg)" ) )()( f )
end

Use it like this:

-- two fixed parameters, third parameter holds vararg list
local vfunc = vararg( 2, function( a, b, arg )
  print( a, b )
  for i,v in ipairs( arg ) do
    print( "", i, v )
  end
end )

vfunc( "a" )
vfunc( "a", "b" )
vfunc( "a", "b", "c" )
vfunc( "a", "b", "c", "d" )

The interface of the vararg function above could work for even earlier versions of Lua, but you probably need a separate implementation in a separate file, because the languages differ too much.

like image 170
siffiejoe Avatar answered Oct 09 '22 12:10

siffiejoe


According to the Lightroom SDK 4 Programmers Guide (PDF):

Lightroom 4 uses version 5.1.4 of the Lua language.

Since Lua 5.1 supports both the old style and the new style of varargs, I think you can just use the new style and not have to worry about forward-compatibility.

like image 43
ruakh Avatar answered Oct 09 '22 14:10

ruakh