There is a method I have been calling:
t1, t2 = LSL:GetDiffItem(item)
where the method is declared as:
GetDiffID(item, ignoreEnchant, ignoreGem, red, yellow, blue, meta, ignorePris)
Now I want to pass additional parameters, skipping some:
item, ignoreEnchant, ignoreGem, red, yellow, blue, meta, ignorePris
I tried just skipping the parameters:
t1, t2 = LSL:GetDiffItem(item, ignore, ignore, , , , , ignore)
But of course that doesn't work:
unexpected symbol near ','
So, how do I skip optional parameters in Lua?
See also
lua.org - 5.3 - Named Arguments "arguments are positional"
Pass nil. This will be identical to not ever having passed the parameter. However, be aware that the documentation states that you can do this, because most functions will not check each individual optional parameter, and only check each parameter if the previous one was provided.
You could use Named Arguments.
As said on lua.org: "This style of parameter passing is especially helpful when the function has many parameters, and most of them are optional. "
The idea is to pass all arguments as a table:
function InfoItem(item)
if item.name then
print("Name: ",item.name)
end
if item.color then
print("Color: ",item.color)
end
if item.enchant then
print("Enchant: ",item.enchant)
end
if item.specialInfo then
print(item.specialInfo)
end
end
InfoItem{name = "Internet Troll's Bane", color = "silver"}
InfoItem{name = "Death's Toenail Clipper", enchant = "unbreakable", specialInfo = "Little effort required to cut through the thickest nails."}
If you're writing your own functions (rather than using a preexisting API), the method I've used is to pass a table as the only parameter to the function, and fill in the appropriate values in that table. Assigning a metatable with the defaults as the first step in your function avoids looking up defaults at each step, but make sure users know you are overwriting the metatable on their input.
Use nil.
note that this won't work when the C code uses gettop, or relys on 'NONE' such as in a switch/case on the type, or explicity checking for none or nil instead of lua_isnoneornil.
Related
I would like to know if it's possible to select a value from a table, based on the argument of a function.
I've tried setting the value statically, and that returns the value. I would just like to do it using function arguments.
function CheckWeapon(ped, attachment)
for k,v in pairs(weapons)do
if GetHashKey(k) == GetSelectedPedWeapon(ped) then
print(v.attachment)
return v.attachment -- This needs to be based on the
-- argument "attachment"
end
end
return false
end
I would expect that if I supplied the argument "silencer" to this function, I would receive the corresponding value for silencer in the table. Instead it's nil. If I type return v.silencer manually, it works though.
In Lua you can index a table 2 ways.
As you have done you can use . such as sometable.key
but this is just syntactic sugar for the other method of indexing, sometable["key"]
both of these use the string key to index the table.
your code could look like:
function CheckWeapon(ped, key)-- where key is a string ie: "attachment"
for k,v in pairs(weapons)do
if GetHashKey(k) == GetSelectedPedWeapon(ped) then
print(v[key])
return v[key]
end
end
return false
end
using the sometable["key"] option also allows for keys that could not be accessed with . such as
sometable["my key"] -- note the space
sometable["1st_key"] -- note it begins with a number
I have a function foo that can get nil values under certain circumstances, i.e. foo(VarA) while VarA is undefined. This undefined VarA should get interpreted as "VarA" but I can't invoke foo("VarA") because VarA should act as an option param (different from normal string params).
mt = {__index = function(t, k) return k end}
setmetatable(_G, mt)
This would get the desired result but now every other undefined variable would return its name. Like abc -> "abc". Do you see any way to only have a metatable active in this specific case? I could switch metatables in my foo method but when I'm in the foo block, the passed param is already nil and its too late.
Appendix: I think the question was not specific enough. Schollii's answer to pass params as a table was good but does not work as intended:
foo({option1 = delete, option2 = push})
This should have the key information (option1 and option2) plus the information of the value (even though delete and push do not exist in global or local namespace). Schollii's approach would give me the key information but not the value information (like "delete" and "push"). I can't define delete and push beforehand because these new "key-words" should get defined by the function itself later on. Passing those new keywords as a string is no option.
It seems like you are developing a domain-specific language within Lua. If that is your intent and you are successful, great. Otherwise, it would be better to stick to more a typical Lua programming style.
Similar to other suggestions:
-- lets the caller decide on the scope of varA
-- and the default string
foo(varA or "varA")
All you need is to test for nil and set VarA's value to its name:
function yourFunc(VarA)
VarA = VarA or "VarA" -- if VarA is nil, it becomes the string "VarA"
... use VarA ...
end
However, you say that VarA should act as an option parameter. I gather you mean that VarA is optional. OK, but Lua does not support named arguments in function calls so if you have
function yourFunc(arg1, arg2, optArg1, optArg2)
...
end
then in order to call yourFunc with optArg2=something, you have to set optArg1 to nil:
yourFunc(1, 2, nil, 3)
In other words you can't do yourFunc(1,2,optArg2=3) which would be pretty neat. But you can get pretty close by having yourFunc accept a table instead of a list of parameters:
function setOptionalArgs(tbl, defaults)
for i,v in ipairs(defaults) do
if tbl[v] == nil then
tbl[v] = v
end
end
for k,v in pairs(defaults) do
if tbl[k] == nil then
tbl[k] = v
end
end
end
function yourFunc(args)
setOptionalArgs(args, {'arg1', arg2=2, 'arg3'})
-- ... use args.arg1, args.arg2 etc ...
print(args.arg1, args.arg2, args.arg3)
end
yourFunc {}
Now you can call
yourFunc {arg1=1}
which will automatically have arg2="arg2". Note that to be clean you should modify setOptionalArgs so only non-array keys get inserted in second loop.
I'm currently teaching myself the Dart language, and my first app doesn't seem to be working right. Here's the code that's causing trouble:
usrLoc = int.parse(query("#txtLoc").text);
When I try to run the app, it opens fine, but when I click the button that triggers this (and three other similar parses), the debugger stops and tells me "Source not found" for int._native_parse(), int._parse(), and int.parse().
Any help would be greatly appreciated.
The text property for the specified element #txtLoc returns an empty string.
The parse method requires that:
The source must be a non-empty sequence of base- radix digits, optionally prefixed with a minus or plus sign ('-' or '+').
You can specify an onError named argument in your call to parse, which takes a callback that handles the invalid input. E.g., if you want the parse call to return the value 42 for all invalid input, you can do this:
usrLoc = int.parse(query("#txtLoc").text, onError: (val) => 42);
If you really expect the element to have some text, you can store the result of query("#txtLoc").text into a separate variable and verify the value. It would also be interesting to check what the real element type is or which tag is marked with id #txtLoc.
If you want to get the content of an input element, you should use the value property instead of text:
query("#txtLoc").value
For example, I have a table
table.insert( t, 1, function()
print ("rock");
end );
Is there any way to get function name from this table. I know that I can store name like a key, but what if I want to keep numeric index and also I want to know function name?
Is there any way to do it?
Thanks, on advance.
Say you have this code:
t = {}
x = 5
table.insert(t, 1, x)
t would then be {[1] = 5}. "5" is just a number - it has no name, and isn't associated with the variable "x"; it's a value.
In Lua, functions are treated exactly the same way, as values:
t = {}
x = function() print("test! :D") end
table.insert(t, 1, x)
The value of x is not associated with x in any way, shape, or form. If you want to manually name a function, you can do it by wrapping the function in a table, for example:
t = {}
x = function() print("test! :D") end
table.insert(t, 1, {
name = "MyFunctionName",
func = x
})
That is how you would do it!
...unless..
..you break the rules!
When Lua was developed, the developers realised that the anonymous nature of functions would make productive error messages difficult to produce, if not impossible.
The best thing you'd see would be:
stdin: some error!
stdin: in function 'unknown'
stdin: in function 'unknown'
So, they made it so that when Lua code was parsed, it would record some debug information, to make life easier. To access this information from Lua itself, the debug library is provided.
Be very careful with functions in this library.
You should exert care when using this library. The functions provided here should be used exclusively for debugging and similar tasks, such as profiling. Please resist the temptation to use them as a usual programming tool: they can be very slow. Moreover, several of these functions violate some assumptions about Lua code (e.g., that variables local to a function cannot be accessed from outside or that userdata metatables cannot be changed by Lua code) and therefore can compromise otherwise secure code.
To achieve your desired effect, you must use the debug.getinfo function; an example:
x = function()
print("test!")
print(debug.getinfo(1, "n").name)
end
x() -- prints "test!" followed by "x"
Unfortunately, the form of debug.getinfo that operates directly on a function doesn't fill the name argument (debug.getinfo(x, "n").name == nil) and the version above requires you to run the function.
It seems hopeless!
...unless..
..you really break the rules.
The debug.sethook function allows you to interrupt running Lua code at certain events, and even change things while it's all happening. This, combined with coroutines, allows you to do some interestingly hacky stuff.
Here is an implementation of debug.getfuncname:
function debug.getfuncname(f)
--[[If name found, returns
name source line
If name not found, returns
nil source line
If error, returns
nil nil error
]]
if type(f) == "function" then
local info = debug.getinfo(f, "S")
if not info or not info.what then
return nil, nil, "Invalid function"
elseif info.what == "C" then
-- cannot be called on C functions, as they would execute!
return nil, nil, "C function"
end
--[[Deep magic, look away!]]
local co = coroutine.create(f)
local name, source, linedefined
debug.sethook(co, function(event, line)
local info = debug.getinfo(2, "Sn")
name = info.namewhat ~= "" and info.name or nil
source, linedefined = info.short_src, info.linedefined
coroutine.yield() -- prevent function from executing code
end, "c")
coroutine.resume(co)
return name, source, linedefined
end
return nil, nil, "Not a function"
end
Example usage:
function test()
print("If this prints, stuff went really wrong!")
end
print("Name = ", debug.getfuncname(test))
This function isn't very reliable - it works sometimes, and doesn't others. The debug library is very touchy, so it's to be expected.
Note that you should never use this for actual release code! Only for debugging!
The most extreme case that is still acceptable is logging errors on piece of released software, to help the developer fix issues. No vital code should depend on functions from the debug library.
Good luck!
The function hasn't got any name. If you want you can assign it to a named variable:
theFunction = t[1]
-- Call it:
theFunction()
If what you want is storing a named function to the table, define it beforehand and use its name to store it:
theFunction = function()
print ("rock");
end
table.insert(t, 1, theFunction)
If this is not what you meant, give more details; for example how you would like to access the function. You're question is a bit misty.
The thing is table.insert considers the table as a sequence, only with numeric keys.
If you want to be able to call the function as t.fun() you'll have to use the table as an associative array and hence use a string as key. (BTW any type except nil or NaN are allowed as key)
t={}
t['MyFun']=function print'foo' end
t.myFun() -- uses syntactic sugar for string keys that are valid identifiers.
You might also notice that functions are passed by reference. So all functions are actually anonymous, and are just stored as a value to a certain key or variable.
You can store the names in a separate table.
functions = {}
functionNames = {}
function addFunction(f, name)
table.insert(functions, f)
functionNames[name] = f
end
To get the function, you can use the index. Once you have the function, you can get its name from function_names:
f = functions[3]
name = functionNames[f]
Good luck!
Some open source I've been using has the below line as a function declaration:
def parse_query(query=nil, options={}, models=nil)
What effect do the "equals" symbols have on the statement? Does it just make the parameters optional?
It sets the default value of the parameter, if the person calling the function does not specify one.
Similar to Python and C++, the equals sign in the parameter list lets you specify a default parameter. For example, in Python:
def hello_world(message="Hello World"):
print "message = "+message
Calling this function like this:
hello_world()
Will result in:
message = Hello World
But calling the function like this:
hello_world("changed default")
results in:
message = changed default