I am looking for a more pleasant way to add an argument name while calling a function.
Something which is better than either of these
local ret = foo( --[[argNam1 =]] true)
local ret = foo( true ) -- first argument is argName1
I tried
local ret = foo( argNam1 = true)
but I got error
')' expected near '='
You could use named parameters, if that's what you want. Lua tables are good for imitating that behavior. So instead of passing all parameters separated by a comma, you pass a single table object; that has named keys.
If that is your foo() function:
local foo(parameters)
print(parameters.argNam1)
end
Then you could call it like: local ret = foo{argNam1 = true}
Or call it like this:
local arguments = {
argNam1 = true,
argNam2 = "foobar"
}
local ret = foo(arguments)
Related
When I execute this code (Windows 10) i get an error from within the library.
local json = loadfile("json.lua")()
local handle = io.popen("curl \"https://someurl.com\"")
local result = handle:read("*all")
handle:close()
local output = json:decode(result)
The error in the console:
lua: json.lua:377: expected argument of type string, got table
stack traceback:
[C]: in function 'error'
json.lua:377: in method 'decode'
monitor.lua:10: in main chunk
[C]: in ?
I'm running the code on Windows 10 with a console and using this library: https://github.com/rxi/json.lua
This function always returns the same error, even if I try different types of arguments, i.e. numbers or strings.
function json.decode(str)
if type(str) ~= "string" then
error("expected argument of type string, got " .. type(str))
end
local res, idx = parse(str, next_char(str, 1, space_chars, true))
idx = next_char(str, idx, space_chars, true)
if idx <= #str then
decode_error(str, idx, "trailing garbage")
end
return res
end
local output = json:decode(result)
is syntactic sugar for
local output = json.decode(json, result)
json is a table.
Hence inside function json.decode the following if statement is entered:
if type(str) ~= "string" then
error("expected argument of type string, got " .. type(str))
end
which produces the observed error.
To fix this you can either change the function definiton to
function json:decode(str)
-- code
end
Or you call
local output = json.decode(result)
You should pick the second one as changing the json library will affect code that already uses json.decode as intended by the author.
This is the sample test code.
s="\\command{sample execution}"
u=string.gsub(s,"\\(%b{})",print)
It works fine as print is global function. I defined function myprint as follows.
myprint = function(x,y)
return print(x,y)
end
Now the command u=string.gsub(s,"\\(%b{})",myprint) does not work. This is because the myprint is not global variable as the print is. So basic question that I want to ask is "How to assign function to global variable in Lua?"
You just need to write:
global_function_1 = function (arg)
-- body
end
or use the syntactic sugar alternative:
function global_function_2 (arg)
-- body
end
Make sure that the part in which you do that doesn't have a local variable with selected name. For instance none of the following functions are global:
local bar
local function foo (arg)
local zee
function arg () end
zee = function () end
function bar () end
end
Please note that I have totally ignored assigning to table members and ignored existence of _G and _ENV, and let's leave it this way.
I think that it is worth mentioning that the string.gsub (or really any function call) doesn't care whenever the function (or any argument) is local or whatever:
local str = "abc"
local function fn (x) print(x) end
string.gsub(str, "%a", fn)
outputs:
a
b
c
I have the following test code which just creates an empty hashmap (containers.map) and fills it up afterwards:
hashtable = containers.Map('KeyType','char','ValueType','double');
hashtable('test') = 1.0;
as long as I use it in my "main" file, everything works fine...
But if I copy these 2 lines into a member function of an self created class, there comes the error:
error: class not found: MyClassName
error: called from
myMemberFunction at line 15 column 31
line 15 is the line where "hashtable('test') = 1.0;" stands.
If I remove this one line, everything works fine again.
I absolutly don't understand, why the error sais, it can not find my class...
I tested my class and everything works perfectly.
I set up the class in the following way:
1: created a folder named: "#MyClassName"
2: created a constructor file named: "MyClassName"
3: added a constructor function named: "function obj = MyClassName(obj)"
4: created a member function file named: "myMemberFunction"
5: created a member function within this file: "function obj = myMemberFunction(obj)
If this code (the hashmap) stands within my constructor it works fine.
Only if it stands inside my memberfunction line 15 "hashtable('test') = 1.0;" makes the error.
tl;dr - replace
hashtable('test') = 1.0;
with
subsasgn( hashtable, substruct( '()', {'test'} ), 1.0 );
Not sure if this is intended behaviour, or a side-effect of containers.Map being a classdef defined class, and whether or not this is because old and new style classes don't play well with each other. May be worth submitting a bug for this. But, seems like the problem is because hashtable('test') is not parsed as intended inside the method - presumably instead of validly treating it as a 'referencing' operation, it treats it as a function call?
In the interest of completeness, here's an MVCE:
% #MyClassName/MyClassName.m
function obj = MyClassName(obj)
obj = struct('myfield', []);
obj = class(obj, 'MyClassName');
end
% #MyClassName/display.m
function display( Obj );
display( [inputname(1), '.myfield = '] );
display( get( Obj, 'myfield' ) );
end
% #MyClassName/get.m
function Out = get( Obj, Field )
Out = struct(Obj).(Field);
end
% #MyClassName/set.m
function Obj = set( Obj, Field, Val )
Obj = struct(Obj);
Obj.(Field) = Val;
Obj = class( Obj, 'MyClassName' );
end
% #MyClassName/myMemberFunction.m
function obj = myMemberFunction(obj)
hashtable = containers.Map('KeyType', 'char', 'ValueType', 'double');
subsasgn( hashtable, substruct( '()', {'test'} ), 1.0 );
obj = set( obj, 'myfield', hashtable );
end
In terminal:
octave:1> a = MyClassName();
octave:2> a = myMemberFunction(a);
octave:3> a
a.myfield =
containers.Map object with properties:
Count : 1
KeyType : char
ValueType : double
I need to define some variables in lua which when accessed result in a call of C++ function:
Lua:
var rootname = root.name; // 'root' acts as a call to c++ function defined below
C++:
class Node
{
std::string name;
}
Node * root()
{
return MyNodeGraph->GetRoot();
}
Is that possible in Lua?
Yes you can do something like that. That's acutally one of the most common use cases of Lua. Although the proper Lua syntax would be local a = prop() if you want a to be 5.
Read https://www.lua.org/manual/5.3/
and https://www.lua.org/pil/24.html
https://www.lua.org/pil/25.html
https://www.lua.org/pil/26.html
Setting metatable of _G might not be part of the "Lua best practices" but here you go:
setmetatable(_G, {
__index = function(t, k)
if k == "root" then
return root_function() -- Call your C function here.
end
return rawget(t, k)
end
})
-- This function is just for a quick test. Call C function instead of this.
function root_function()
print("in root_function")
return { name = "hello" }
end
--
-- Test
rootname = root.name
print(rootname) -- Prints "hello"
I need to get the variable a function's return value is assigned to.
function example()
end
variable = 3 --just for example
variable = example() --I need the value of variable(in this case 3) passed as an argument to example()
Please read the Lua reference on how to call and define functions.
https://www.lua.org/manual/5.3/manual.html#3.4.10
https://www.lua.org/manual/5.3/manual.html#3.4.11
You can simply do this:
function fancyFunction(val)
return val
end
local val = 3
val = fancyFunction(val)
of course this minimum example does not make much sense. You should of course have another return value than your argument. Otherwise you don't have to call the function in the first place.
(Quite hard to understand what you're trying to do.) Could you possibly be referring to object oriented programming? If so, then you need something like this:
--setup
t = {}
function t:set(v) self.value = v end --assign value to 'variable'
function t:get() return self.value end
--use
t:set(3)
print(t:get())