Create Lua function from string - lua

I am creating functions (of x) from a string in Lua. The code I am using is
function fcreate(fs)
return assert(loadstring("return function (x) return " .. fs.." end"))()
end
This works for globals, e.g.
u=fcreate("math.sin(x)")
does the right thing.
However, it does not seem to like local variables. So
local c=1
u=fcreate("math.sin(x)+c")
will not work because c is local.
Is this fixable?

"loadstring does not compile with lexical scoping", so no, it can't see locals outside the loadstring call.
Is this fixable?
That depends. Why are you using loadstring in the first place? Lua supports closures as first class values, so I can't see from your example why you'd need loadstring.
Your example:
u = fcreate("math.sin(x)+c")
Can be rewritten without the need for loadstring or your fcreate function:
u = function(x) return math.sin(x)+c end
Which of course is the same as:
function u(x) return math.sin(x) + c end
I can see a case for loadstring if you have user-configurable expressions that you wanted to compile into some other function, but your case with the local c suggests that's not the case. Are you trying to make some kinda of home-rolled lamda syntax?

Can't be done in any reasonable way. For an example of why, look at this:
function makefunction(name)
local a = 1
local b = 2
local c = 3
-- ...
return assert(loadstring("return " .. name))
end
local a = 4
local func = makefunction("a")
print(func())
If this worked, what is printed? 1 or 4? Does it capture the variable from the place where the function was loaded, even though that function doesn't exist anymore? Or does it look it up from the place where it was called?
The first would mean that the function is lexically scoped wherever it's created. Being able to access the variable after the function has exited means that the variable would need to be promoted into an upvalue dynamically, which is not something that Lua can do at the moment. As it is now, Lua can see every access to a local variable during compilation, so it knows which variables to turn into upvalues (at a performance hit) and which to keep as locals.
The second would mean that variable accesses inside a loadstring'd function would work completely different than every other access in Lua: Lua uses lexical scoping, not dynamic scoping. It'd be a huge implementation change in Lua, and an extremely inconsistent one.
So, neither is supported. You can control the environment of a dynamically loaded function, using setfenv in Lua 5.1 or the env parameter of load(...) in Lua 5.2, but neither of those let you access local variables automatically.

Something you could do if you don't need to mutate the local variables is to pass those values as arguments to the generated function. You would still need to manually specify the variables to close over but its better then nothing.
For example, you can build up your closure to look like
return (function(a,b,c)
return function(x) return print(a, x) end
end)(...)
We might do that by changing your function to look like
function fcreate(variables, fs)
local varnames = {}
local varvalues = {}
local nvars = 0
for n,v in pairs(variables) do
nvars = nvars + 1
table.insert(varnames, n)
table.insert(varvalues, v)
end
local chunk_str = (
'return (function(' .. table.concat(varnames, ',') .. ') ' ..
'return function(x) return ' .. fs .. ' end ' ..
'end)(...)'
)
return assert( loadstring(chunk_str) )( unpack(varvalues, 1, nvars) )
end
local a = 1;
local f = fcreate({a=a}, 'x+a')
print(f(1), f(2))

Related

Evaluating expression in Lua in an Environment

This question has some reference to the question Evaluating expression in Lua in Mathematics Environment
The following code works.
tbl = {}
tbl.sin = math.sin
tbl.cos = math.cos
function mathEval(exp)
return load("return " .. exp, exp, "t", tbl)()
end
print(mathEval("sin(0)"))
print(mathEval("sin(0)+cos(1)+2^2"))
However, the following code does not work.
tbl = {}
tbl.sin = math.sin
tbl.cos = math.cos
function mathEval(exp)
return load("return " .. tostring(exp), tostring(exp), "t", tbl)()
end
print(mathEval(sin(0)))
print(mathEval(sin(0)+cos(1)+2^2))
I want to evaluate expressions without using quotes. How can that be done?
The problem with the line print(mathEval(sin(0)+cos(1)+2^2)) is that the argument of mathEval is evaluated before mathEval runs, so evaluating the variables sin and cos can not be deferred to the environment of mathEval; that is, mathEval gets a value, and no expression to evaluate at all!
First of all, one option to evaluate such mathematical expressions without the use of mathEval would be to simply temporarily change your environment:
local prev_env = _ENV -- this is needed to restore the environment later on
_ENV = tbl -- enter custom environment
local result = sin(0)+cos(1)+2^2
_ENV = prev_env -- restore environment
print(result)
if you want mathEval as a convenience helper, you'll have to pass the expression as a function returning the value to the expression such that calling the function will evaluate the expression; this allows you to defer the initialization. You'll have to use a powerful function called setfenv which allows you to change the environment of func; this was unfortunately removed in favor of _ENV in Lua 5.2 and later. The code then becomes trivial:
local function mathEval(func)
setfenv(func, tbl)
return func
end
mathEval(function() return sin(0)+cos(1)+2^2 end)
setfenv can be replicated in Lua 5.2 using the debug library, since Lua internally implements _ENV as an upvalue, as shown by Leafo:
local function setfenv(fn, env)
local i = 1
while true do
local name = debug.getupvalue(fn, i)
if name == "_ENV" then
debug.upvaluejoin(fn, i, (function()
return env
end), 1)
break
elseif not name then
break
end
i = i + 1
end
return fn
end
I assume you do not want to evaluate the expression before passing the result as an argument? Then you could wrap your expression into a function, which is then lazily called. It replaces the environment with tbl, executes the function, and reverts the environment.
tbl = {}
tbl.sin = math.sin
tbl.cos = math.cos
function mathEval(func)
local old = _ENV
_ENV = tbl
local r = func()
_ENV = old
return r
end
print(mathEval(function() return sin(0)+cos(1)+2^2 end))
You are passing sin(0) and sin(0)+cos(1)+2^2 to the mathEval(exp) function, but since sin and cos are not global variables and the math library is not being passed as an environment, Lua is unable to find them.
If you want to use math functions with the mathEval function, you can use the tbl table created before, to call the math functions, for example:
print(mathEval("tbl.sin(0)"))
print(mathEval("tbl.sin(0)+tbl.cos(1)+2^2"))
or alternatively you can pass the math library or the math functions as an upvalue to the load() function:
function mathEval(exp)
return load("return " .. tostring(exp), tostring(exp), "t", _ENV)()
end
print(mathEval("math.sin(0)"))
print(mathEval("math.sin(0)+math.cos(1)+2^2"))
It is possible to do this without quotes, this should work:
expression = string.format("%s(%d)", "math.sin", 0)
fn = load( "return " .. expression)
result = fn()
print(result) -- Output: 0
In this example, the string.format() function is used to create the string "math.sin(0)". The resulting string is then passed to the load() function as before.
In this way you don't need to use quotes on the string, and you can use placeholders to concatenate the variables.

Use of _ENV in Lua function does not have effect

I'm reviewing some toy examples from Lua and I found the following one over there with respect to environments:
M = {} -- the module
complex = {} -- global complex numbers registry
mt = {} --metatable for complex numbers
function new (r, i)
local cp = {}
cp = {r=r, i=i}
return setmetatable(cp,mt)
end
M.new = new -- add 'new' to the module
function M.op (...)
--Why does not it work?
local _ENV = complex
return ...
end
function M.add (c1, c2)
return new(c1.r + c2.r, c1.i + c2.i)
end
function M.tostring (c)
return string.format("(%g,%g)", c.r, c.i) --to avoid +-
end
mt.__tostring = M.tostring
mt.__add = M.add
complex.a = M.new(4,3)
complex.b = N.new(6,2)
--nil
M.op(a+b)
--It works
M,op(complex.a+complex.b)
The use of _ENV has no effect. However, if I use complex = _G, both lines work. How do set a local environment for M.op. I'm not asking for specific libraries, I just want to know why it does not work and how to fix it.
M.op(a+b)
This line doesn't do what you expect, because it uses values of a and b that are available when this method is called. It doesn't matter that you set _ENV value inside the method, as by the time the control gets there, the values referenced by a and b have already been retrieved and since both values are nil in your code, you probably get "attempt to perform arithmetic on global..." error.
how to fix it.
I'm not sure what exactly you want to fix, as you already reference the example that works. If you assign complex.a you can't assume that a will have the same value without mapping complex table to _ENV.

Lua - get table hex identifier

I want to know how to get the table hex id. I know that doing:
local some_var = {}
print (some_var)
the result is (for instance):
table: 0x21581c0
I want the hex without the table: string. I know that maybe some of you suggest me to make a regular expression (or something similar) to remove those chars, but I want to avoid that, and just get the 0x21581c0
Thanks
This is simpler and works for all types that are associated with pointers:
local function getId(t)
return string.format("%p", t)
end
print("string:", getId("hi"))
print("table:", getId({}))
print("userdata:", getId(io.stdin))
print("function:", getId(print))
print("number:", getId(1))
print("boolean:", getId(false))
print("nil:", getId(nil))
Result:
string: 0x0109f04638
table: 0x0109f0a270
userdata: 0x01098076c8
function: 0x0109806018
number: NULL
boolean: NULL
nil: NULL
In the standard implementation, there is the global 'print' variable that refers to a standard function that calls, through the global variable 'tostring', a standard function described here. The stanard 'tostring' function is the only way to retrieve the hexadecimal number it shows for a table.
Unfortunately, there is no configuration for either of the functions to do anything differently for all tables.
Nonetheless, there are several points for modification. You can create you own function and call that every time instead, or point either of the the global variables print or tostring to you own functions. Or, set a __tostring metamethod on each table you need tostring to return a different answer for. The advantage to this is it gets you the format you want with only one setup step. The disadvantage is that you have to set up each table.
local function simplifyTableToString(t)
local answer = tostring(t):gsub("table: ", "", 1)
local mt = getmetatable(t)
if not mt then
mt = {}
setmetatable(t, mt)
end
mt.__tostring = function() return answer end
end
local a = {}
local b = {}
print(a, b)
simplifyTableToString(a)
print(a, b)
Without complex patterns, you can just search for the first space, and grab the substring of what follows.
function get_mem_addr (object)
local str = tostring(object)
return str:sub(str:find(' ') + 1)
end
print(get_mem_addr({})) -- 0x109638
print(get_mem_addr(function () end)) -- 0x108cf8
This function will work with tables and functions, but expect errors if you pass it anything else.
Or you can use a little type checking:
function get_mem_addr (o)
return tostring(o):sub(type(o):len() + 3)
end
The table id stated by the OP is invalid in the version of Lua I am using (5.1 in Roblox). A valid ID is length 8, not 9 as in your example. Either way, just use string.sub to get the sub-string you are after.
string.sub(tostring({}), 8)
The reason is, 'table: ' is 7 characters long, so we take from index 8 through the end of the string which returns the hex value.

How can I detect when the Lua scripts access a global variable?

I started to work with a C++/Lua codebase that is somewhat a mess, and when I dump the contents of _G in the middle of the application execution, there are hundreds of variables that I am sure were only initialized somewhere, but are not used anywhere else in the code anymore. To clean this up, I would like to setup a mechanism that will log whenever Lua accesses a global variable.
This was my idea of how to achieve this – I wanted to setup a proxy _G that would only pass all read and write accesses via __index and __newindex along to its own copy of the original _G. However this simple script doesn't work and only outputs:
C:\Programs\lua-5.1.5_Win32_bin\lua5.1: error in error handling
GProx =
{
vars = _G
}
setmetatable(GProx, {
__index = function (t, name)
print("Read> " .. name)
return t.vars[name]
end,
__newindex = function (t, name, val)
print("Write> " .. name .. ' = ' .. val)
t.vars[name] = val
end
})
setfenv(0, GProx)
a = 1 --> Expected to print 'Write> a'
print(a) --> Expected to print 'Read> print', 'Read> a', and '1'
Is this a good approach or is there a better way to do this?
If this is a valid line of thought, then what is the problem with my snippet?
Try this snippet instead, it will work with reads and writes:
do
-- Use local variables
local old_G, new_G = _G, {}
-- Copy values if you want to silence logging
-- about already set fields (eg. predeclared globals).
-- for k, v in pairs(old_G) do new_G[k] = v end
setmetatable(new_G, {
__index = function (t, key)
print("Read> " .. tostring(key))
return old_G[key]
end,
__newindex = function (t, key, val)
print("Write> " .. tostring(key) .. ' = ' .. tostring(val))
old_G[key] = val
end,
})
-- Set it at level 1 (top-level function)
setfenv(1, new_G)
end
Here's a rundown of the changes:
A block is used to have a local reference to the old _G. In your proposed implementation, if a global variable named vars is set, it will override GProx.vars and break the proxy.
key and val should go through tostring before printing, since most values (ie. tables) aren't implicitly converted to strings.
Setting the environment at level 1 is usually enough and will not mess with Lua's internal workings.
You can set a metatable directly on the _G table, as explained in PIL section 14.2, so you are really close. There are also a couple of existing Lua modules on the web that do this (perhaps penlight contains one).

What's the difference between these two Lua examples? Is one better?

I'm just getting started with Lua. In the example I'm learning from (the Ghosts & Monsters Corona open source), I see this pattern repeatedly.
local director = require("director")
local mainGroup = display.newGroup()
local function main()
mainGroup:insert(director.directorView)
openfeint = require ("openfeint")
openfeint.init( "App Key Here", "App Secret Here", "Ghosts vs. Monsters", "App ID Here" )
director:changeScene( "loadmainmenu" )
return true
end
main()
Is this some sort of convention experienced Lua programmers recommend or are there genuine advantages to doing it this way? Why wouldn't you just skip the function all together and do this:
local director = require("director")
local mainGroup = display.newGroup()
mainGroup:insert(director.directorView)
local openfeint = require ("openfeint")
openfeint.init( "App Key Here", "App Secret Here", "Ghosts vs. Monsters", "App ID Here" )
director:changeScene( "loadmainmenu" )
Is there some implicit benefit to the first style over the second? Thanks!
Is this some sort of convention experienced Lua programmers recommend or are there genuine advantages to doing it this way?
It's not typical. The advantage is that object state is private, but that's not enough of an advantage to recommend it.
I see this pattern repeatedly.
I've never seen it before, and it happens only once in the source you posted.
EDIT: Adding a response to a question asked in the comments below this post.
A function which accesses external local variables binds to those variables and is called a 'closure'. Lua (for historical reasons) refers to those bound variables as 'upvalues'. For example:
local function counter()
local i = 1
return function()
print(i)
i = i + 1
end
end
local a, b = counter(), counter()
a() a() a() b() --> 1 2 3 1
a and b are closures bound to different copies of i, as you can see from the output. In other words, you can think of a closure as function with it's own private state. You can use this to simulate objects:
function Point(x,y)
local p = {}
function p.getX() -- syntax sugar for p.getX = function()
return x
end
function p.setX(x_)
x = x_
end
-- for brevity, not implementing a setter/getter for y
return p
end
p1 = Point(10,20)
p1.setX(50)
print(p1.getX())
Point returns a table of closures, each bound to the locals x and y. The table doesn't contain the point's state, the closures themselves do, via their upvalues. An important point is that each time Point is called it creates new closures, which is not very efficient if you have large quantities of objects.
Another way of creating classes in Lua is to create functions that take a table as the first argument, with state being stored in the table:
function Point(x,y)
local p = {x=x,y=y}
function p:getX() -- syntax sugar for p.getX = function(self)
return self.x
end
function p:setX(x)
self.x = x
end
return p
end
p1 = Point(10,20)
p1:setX(50) -- syntax sugar for p1.setX(p1, 50)
print(p1:getX()) -- syntax sugar for p1.getX(p1)
So far, we're still creating new copies of each method, but now that we're not relying on upvalues for state, we can fix that:
PointClass = {}
function PointClass:getX() return self.x end
function PointClass:setX(x) self.x = x end
function Point(x,y)
return {
x = x,
y = y,
getX = PointClass.getX,
setX = PointClass.getY,
}
end
Now the methods are created once, and all Point instances share the same closures. An even better way of doing this is to use Lua's metaprogramming facility to make new Point instances automatically look in PointClass for methods not found in the instance itself:
PointClass = {}
PointClass.__index = PointClass -- metamethod
function PointClass:getX() return self.x end
function PointClass:setX(x) self.x = x end
function Point(x,y)
return setmetatable({x=x,y=y}, PointClass)
end
p1 = Point(10,20)
-- the p1 table does not itself contain a setX member, but p1 has a metatable, so
-- when an indexing operation fails, Lua will look in the metatable for an __index
-- metamethod. If that metamethod is a table, Lua will look for getX in that table,
-- resolving p1.setX to PointClass.setX.
p1:setX(50)
This is a more idiomatic way of creating classes in Lua. It's more memory efficient and more flexible (in particular, it makes it easy to implement inheritance).
I frequently write my own Lua scripts this way because it improves readability in this case:
function main()
helper1( helper2( arg[1] ) )
helper3()
end
function helper1( foo )
print( foo )
end
function helper2( bar )
return bar*bar
end
function helper3()
print( 'hello world!' )
end
main()
This way the "main" code is at the top, but I can still define the necessary global functions before it executes.
A simple trick, really. I can't think of any reason to do this besides readability.
The first style could be used too improove readability, but I would rather give the function some meaningful name instead of main or just go without the function.
By the way, I think it's always a good practice to name blocks of code, i.e. put them into functions or methods. It helps explain your intend with that piece of code, and encourages reuse.
I don't see much point to the first style as you've shown it. But if it said something like if arg then main() end at the bottom, the script might (just might) be useful as a loadable "library" in addition to being a standalone script. That said, having a main() like that smacks of C, not Lua; I think you're right to question it.

Resources