It is currently June 19th, 2021, 6:03 pm

Get nth argument of a Lua function

Discuss the use of Lua in Script measures.
User avatar
Yincognito
Posts: 3221
Joined: February 27th, 2015, 2:38 pm
Location: Terra Yincognita

Get nth argument of a Lua function

Post by Yincognito »

I have this kind of Lua function (heavily simplified and not working, posted just to get an idea what I'm after):

Code: Select all

function GetIndex(groupindex, classindex, fieldindex, valueindex, whichindex, direction, browsestyle)
  print(arg[whichindex])
end
Basically, I want to get the whichindex-th function argument of GetIndex(), so if I call it like GetIndex(7,1,5,2,3,1,1) I want to print the 3-rd argument of the function, i.e. 5. The code above doesn't work, probably because it expects a variable number of arguments being used (i.e. ...), but how can I get what I need for a fixed number of arguments function like this? Besides that, I read there are some changes from Lua 5.0 to higher versions in this regard, so the approach should work with higher versions as well.
User avatar
jsmorley
Developer
Posts: 21776
Joined: April 19th, 2009, 11:02 pm
Location: Fort Hunt, Virginia, USA

Re: Get nth argument of a Lua function

Post by jsmorley »

Yincognito wrote: May 22nd, 2021, 2:40 pm I have this kind of Lua function (heavily simplified and not working, posted just to get an idea what I'm after):

Code: Select all

function GetIndex(groupindex, classindex, fieldindex, valueindex, whichindex, direction, browsestyle)
  print(arg[whichindex])
end
Basically, I want to get the whichindex-th function argument of GetIndex(), so if I call it like GetIndex(7,1,5,2,3,1,1) I want to print the 3-rd argument of the function, i.e. 5. The code above doesn't work, probably because it expects a variable number of arguments being used (i.e. ...), but how can I get what I need for a fixed number of arguments function like this? Besides that, I read there are some changes from Lua 5.0 to higher versions in this regard, so the approach should work with higher versions as well.
Yeah the arg[] array is only created when you define the function with ... variable arguments. I'm not sure there is an easy, logical way to do what you want. I'd be tempted to redefine the function to use variable arguments, and then just use all the results based on their position in the the arg[] array. You can loop through the array and assign the values to regular variables like valueindex or whatever if you want.
User avatar
Yincognito
Posts: 3221
Joined: February 27th, 2015, 2:38 pm
Location: Terra Yincognita

Re: Get nth argument of a Lua function

Post by Yincognito »

jsmorley wrote: May 22nd, 2021, 3:29 pm Yeah the arg[] array is only created when you define the function with ... variable arguments. I'm not sure there is an easy, logical way to do what you want. I'd be tempted to redefine the function to use variable arguments, and then just use all the results based on their position in the the arg[] array. You can loop through the array and assign the values to regular variables like valueindex or whatever if you want.
Indeed - thank you for taking a look. ;-) In the end I managed to achieve what I wanted, by changing the order of arguments in the function, so that the "iterated" ones come last, as variable number of arguments (i.e. ...):

Code: Select all

function GetIndex(whichindex, direction, browsestyle, ...)
  print(arg[whichindex])
end
It required some modifications to the code, like replacing, say, all instances of groupindex with arg[1] and it led to some more complex (but shorter) syntax like:

Code: Select all

items[arg[1]][2][arg[2]][2][arg[3]][2][oldindex][1]
instead of

Code: Select all

items[groupindex][2][classindex][2][fieldindex][2][oldindex][1]
(items is the table I use with these indexes), but it works nevertheless and it's not like the actual code wasn't a bit complex earlier anyway - now it looks like this:

Code: Select all

function GetIndex(whichindex, direction, browsestyle, ...)
  local oldindex, newindex, maxindex = arg[whichindex], arg[whichindex], {GroupCount, ClassCount, FieldCount, ValueCount}
  repeat
    if newindex + direction < 1 or newindex + direction > maxindex[whichindex] then newindex = oldindex; break else newindex = newindex + direction end
  until (browsestyle == 1 and true) or
        (browsestyle == 2 and
          ((whichindex == 1 and string.gsub(items[oldindex][1], '%s*:.*$', '') == string.gsub(items[newindex][1], '%s*:.*$', '')) or
           (whichindex == 2 and string.gsub(items[arg[1]][2][oldindex][1], '%s*:.*$', '') == string.gsub(items[arg[1]][2][newindex][1], '%s*:.*$', '')) or
           (whichindex == 3 and string.gsub(items[arg[1]][2][arg[2]][2][oldindex][1], '%s*:.*$', '') == string.gsub(items[arg[1]][2][arg[2]][2][newindex][1], '%s*:.*$', '')) or
           (whichindex == 4 and string.gsub(items[arg[1]][2][arg[2]][2][arg[3]][2][oldindex][1], '%s*:.*$', '') == string.gsub(items[arg[1]][2][arg[2]][2][arg[3]][2][newindex][1], '%s*:.*$', '')))) or
        (browsestyle == 3 and
          ((whichindex == 1 and string.gsub(items[oldindex][1], '%s*:.*$', '') ~= string.gsub(items[newindex][1], '%s*:.*$', '')) or
           (whichindex == 2 and string.gsub(items[arg[1]][2][oldindex][1], '%s*:.*$', '') ~= string.gsub(items[arg[1]][2][newindex][1], '%s*:.*$', '')) or
           (whichindex == 3 and string.gsub(items[arg[1]][2][arg[2]][2][oldindex][1], '%s*:.*$', '') ~= string.gsub(items[arg[1]][2][arg[2]][2][newindex][1], '%s*:.*$', '')) or
           (whichindex == 4 and string.gsub(items[arg[1]][2][arg[2]][2][arg[3]][2][oldindex][1], '%s*:.*$', '') ~= string.gsub(items[arg[1]][2][arg[2]][2][arg[3]][2][newindex][1], '%s*:.*$', ''))))
  return newindex
end
P.S. The actual code could have been shortened further by using load(chunk) to compile a variable string (since some code repeats itself with only minor changes), but I'll let using load() for some other time, considering I'm not sure of the performance impact either.
User avatar
jsmorley
Developer
Posts: 21776
Joined: April 19th, 2009, 11:02 pm
Location: Fort Hunt, Virginia, USA

Re: Get nth argument of a Lua function

Post by jsmorley »

If you say so... ;-)

I was going to suggest something like this:

Code: Select all

function Update()
	GetIndex(7,1,5,2,3,1,1)
end

function GetIndex(...)
	groupindex = arg[1]
	classindex = arg[2]
	fieldindex = arg[3]
	valueindex = arg[4]
	whichindex = arg[5]
	direction = arg[6]
	browsestyle = arg[7]
	
	print(arg[whichindex])
end
User avatar
Yincognito
Posts: 3221
Joined: February 27th, 2015, 2:38 pm
Location: Terra Yincognita

Re: Get nth argument of a Lua function

Post by Yincognito »

jsmorley wrote: May 22nd, 2021, 4:08 pm If you say so... ;-)

I was going to suggest something like this:

Code: Select all

function Update()
	GetIndex(7,1,5,2,3,1,1)
end

function GetIndex(...)
	groupindex = arg[1]
	classindex = arg[2]
	fieldindex = arg[3]
	valueindex = arg[4]
	whichindex = arg[5]
	direction = arg[6]
	browsestyle = arg[7]
	
	print(arg[whichindex])
end
I understood the idea from your earlier post, and it's excellent. Thing is, I had already rewritten the whole thing using the arguments' "switch" approach as you were writing your reply, and I was interested in as short of a code as possible too (one of the things I like about Lua snippets), so I went on with my initial idea. In other words, it was just a matter of having the stuff rewritten already, otherwise I would have probably approached this as you suggested.

Many thanks again for your spot on advice. :rosegift:

P.S. If Lua had a case statement, the actual code could have been even cleaner.
User avatar
jsmorley
Developer
Posts: 21776
Joined: April 19th, 2009, 11:02 pm
Location: Fort Hunt, Virginia, USA

Re: Get nth argument of a Lua function

Post by jsmorley »

User avatar
Yincognito
Posts: 3221
Joined: February 27th, 2015, 2:38 pm
Location: Terra Yincognita

Re: Get nth argument of a Lua function

Post by Yincognito »

Yes, I read that (and others) a couple of times already, LOL - the simple table of functions approach there would have been what I needed, but it's one thing when one has the needed statement and another when he has to write additional code to replicate it. In such cases, looking for simplicity / clarity can lead to writing more complex code, which defeats the purpose of the "quest" in the first place. :confused:
User avatar
jsmorley
Developer
Posts: 21776
Joined: April 19th, 2009, 11:02 pm
Location: Fort Hunt, Virginia, USA

Re: Get nth argument of a Lua function

Post by jsmorley »

It's worth putting in your mental toolbox how variable arguments work with the arg[] table...

Note that if you try to fool it with:

Code: Select all

function Update()
  GetIndex(7,1,5,2,3,1,1,99)
end

function GetIndex(groupindex, classindex, fieldindex, valueindex, whichindex, direction, browsestyle, ...)
  print(arg[whichindex])
end
It won't work. It will print "nil". The array exists, but there is no 3rd parameter in the arg[] table. How it behaves is that ONLY the arguments that are passed as part of the ... "variable" parameters (the vararg list) will be created in the arg[] table. The variable "whichindex" certainly exists and contains "3", but the 3rd argument it is pointing to is not indexed in arg[]. So in this instance this:

Code: Select all

function Update()
  GetIndex(7,1,5,2,3,1,1,99)
end

function GetIndex(groupindex, classindex, fieldindex, valueindex, whichindex, direction, browsestyle, ...)
  print(arg[1])
end
Would print "99", which is the first and only argument value contained in the vararg list / arg[] table.

If you use this:

Code: Select all

function Update()
  GetIndex(7,1,5,2,3,1,1,99)
end

function GetIndex(groupindex, classindex, fieldindex, valueindex, whichindex, direction, browsestyle, ...)
  print(#arg)
end
You will see that it prints "1" as the size of the vararg list / arg[] table.
User avatar
Yincognito
Posts: 3221
Joined: February 27th, 2015, 2:38 pm
Location: Terra Yincognita

Re: Get nth argument of a Lua function

Post by Yincognito »

jsmorley wrote: May 23rd, 2021, 11:31 am It's worth putting in your mental toolbox how variable arguments work with the arg[] table...

Note that if you try to fool it with:

Code: Select all

function Update()
  GetIndex(7,1,5,2,3,1,1,99)
end

function GetIndex(groupindex, classindex, fieldindex, valueindex, whichindex, direction, browsestyle, ...)
  print(arg[whichindex])
end
It won't work. It will print "nil". The array exists, but there is no 3rd parameter in the arg[] table. How it behaves is that ONLY the arguments that are passed as part of the ... "variable" parameters (the vararg list) will be created in the arg[] table. The variable "whichindex" certainly exists and contains "3", but the 3rd argument it is pointing to is not indexed in arg[]. So in this instance this:

Code: Select all

function Update()
  GetIndex(7,1,5,2,3,1,1,99)
end

function GetIndex(groupindex, classindex, fieldindex, valueindex, whichindex, direction, browsestyle, ...)
  print(arg[1])
end
Would print "99", which is the first and only argument value contained in the vararg list / arg[] table.

If you use this:

Code: Select all

function Update()
  GetIndex(7,1,5,2,3,1,1,99)
end

function GetIndex(groupindex, classindex, fieldindex, valueindex, whichindex, direction, browsestyle, ...)
  print(#arg)
end
You will see that it prints "1" as the size of the vararg list / arg[] table.
Correct. I did pass the arguments I wanted to "iterate" to the ... vararg list in my approach though (simplified code):

Code: Select all

function GetIndex(whichindex, direction, browsestyle, ...)
  print(arg[whichindex])
end
and called it like:

Code: Select all

function Update()
  GetIndex(3,1,1,7,1,5,2)
end
Notice that now I call the function using GetIndex(3,1,1,7,1,5,2) instead of GetIndex(7,1,5,2,3,1,1) like before.

Basically, I "moved" the former groupindex, classindex, fieldindex, valueindex arguments at the end (or to the "right"), as part of the ... vararg list, when calling the function. This allowed me to keep the whichindex, direction, browsestyle arguments unchanged (and not needing arg[] to get their values), while I could do the arg[] reference for the "rightmost" arguments, i.e. those I needed the feature to work for, that is.
User avatar
jsmorley
Developer
Posts: 21776
Joined: April 19th, 2009, 11:02 pm
Location: Fort Hunt, Virginia, USA

Re: Get nth argument of a Lua function

Post by jsmorley »

Right. I knew you knew already, but I just wanted to put it out there for posterity.