lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


Setting the environment explicitly works, but that doesn't really help me write the tighter syntax that I want. 
For instance, this does allow me to use the syntax I want:

function getEnv()
    local env = {}
    local i = 1
    while true do
        local localVar, value = debug.getlocal(3, i)
        if localVar ~= nil then
            env[localVar] = value
        else
            break
        end
        i = i + 1
    end
    setmetatable(env, {__index = _G})
    return env
end

function eval(s)
    local f = assert(loadstring(s))
    setfenv(f, getEnv())
    f()
end

function flarp()
    local myLocal = "hello"  
    eval[[print(myLocal)]]
end

flarp()

(prints hello)

... but it uses the debug library and has a nice fat function call overhead.


On 1/17/07, Sam Roberts <sroberts@bycast.com> wrote:
On Tue, Jan 16, 2007 at 10:53:47PM -0800, Matthew Armstrong wrote:
> Cool, thanks for your help.
>
> The reason I asked is I want to try to mimic "eval" functionality, found in
> some other scripting languages, such as perl.
>
> Lua has loadstring, but this operates in the global environment, and
> afaik/remember, perl puts more context into its eval.

With lua, you put the context in after, with setfenv().

> All I'm really going for here is tighter syntax, as I'm trying to adapt lua
> into a sort of higher level language to suit our purposes.
>
> For instance, we have a trigger object, which will fire when a certain event
> occurs.  One specialization of the trigger is a conditional version, which
> fires when a particular condition is true.  Creating a conditional trigger
> looks something like this:
>
> TCond(function() return a > b end)
>
> but I'd like to shorten it to:
>
> TCond[[a > b]]

...

> But I'm running into trouble, because loadstring can't access local
> variables 'a' and 'b' in the environment.


Technically, where a and b are isn't an environment, not as lua uses the
term "environment", but instead of making a and b local, and instead of
making them global, put them into a function environment specific
to the evaluation of the condition?

Then the TCond<code> has its own environment it can operate in, you can
specify exactly what will appear there, including preventing global env
access, if you wish.

Clunky example:

  > function f() p = loadstring"print(a)"; setfenv(p, {a='hello',print=print}); p(); end
  > f()
  hello

or

  state = {a=1, b=2}
  function TCond(trigger) condition = loadstring('return '..trigger); setfenv(condition, state) end
  print(condition())

Sam