LUA Environment Exploration

Source: Internet
Author: User
Tags define local lua

What is the environment?

http://www.lua.org/manual/5.1/manual.html#2.9

Besides Metatables, objects of types thread, function, and UserData has another table associated with them, called their Environment. Like Metatables, environments is regular tables and multiple objects can share the same environment.

threads, functions, and user-defined data, a table associated with it, the environment table, the environment table is also a general table, and multiple objects can share the same environment table.

Threads is created sharing the environment of the creating thread. Userdata and C functions are created sharing the environment of the creating C function. non-nested Lua functions (created loadfile by, loadstring or) is created sharing the environment of the load creating thread. Nested LUA functions is created sharing the environment of the creating Lua function.

The created thread shares the environment where the threads are created.

The created user data and the C function share the Creator (C function) environment.

non-nested Lua functions (by LoadFile and loastring and load) are created and shared by the creator (thread) of the environment.

The Nested Lua function is created, sharing the creator (LUA function) environment.

Environments associated with threads is called global environments. They is used as the default environment for threads and non-nested Lua functions created by the thread and can is Directl y accessed by C code (see§3.3).

The environment of the associated thread, called the Global environment. When threads and non-nested functions are created by threads, the default environment is the global environment, which can be accessed directly by C code.

The environment associated with a C function can is directly accessed by C code (see§3.3). It is used as the default environment for other C functions and UserData created by the function.

The C function is associated with an environment that can be accessed directly by C code.

C functions and user data that are created by the function, the environment is used as the default environment.

Environments associated with Lua functions is used to resolve all accesses to global variables within the function (see§ 2.3). They is used as the default environment for nested LUA functions created by the function.

The environment associated with the LUA function is used as an access to resolve all global functions, in this function.

This environment is used as the default environment for the following scenarios, the LUA function creates the nested LUA function, then the nested LUA function, the environment that integrates the LUA function.

You can change the environment of a Lua function or the running thread by calling setfenv . You can get the environment of a Lua function or the running thread by calling getfenv . To manipulate the environment of other objects (UserData, C functions, and other threads) you must use the C API.

Use setfenv to change the environment of LUA functions or threads.

Use getfenv to get the environment for LUA functions or threads.

To manipulate the environment of other objects (UserData C functions Other threads), you need to use the C API.

LUA thread

The type thread represents independent threads of execution and it is used to implement Coroutines (see§2.11). Do not confuse Lua threads with Operating-system threads. Lua supports coroutines on all systems, even those.

Threads express an independent execution thread that is used to implement the process.

Do not confuse the threads of a LUA thread with the threading of the operating system.

LUA supports co-processes on all systems, even on systems that do not support threading.

Co-process

Lua supports Coroutines, also called Collaborative multithreading. A Coroutine in Lua represents an independent thread of execution. Unlike threads in multithread systems, however, a coroutine only suspends it execution by explicitly calling a yield func tion.

http://www.lua.org/manual/5.1/manual.html#2.11

Http://www.cnblogs.com/chenny7/p/3634529.html

A co-Program (Coroutine) is similar to a thread in a multithreaded situation: it has its own stack, local variables, instruction pointers, but shares global variables with other processes, and so much more.

The process is similar to a multi-threading, but there are many differences from multithreading:

1. The process is not an OS thread, so creating and switching overhead is smaller than the thread.
2. The co-process has its own stack, local variables and so on, but the stack is simulated in user process space, so the cost of creating and switching is very small.
3. Multithreaded programs are executed concurrently by multiple threads, that is, there are multiple control flows executing at a moment. And the process is to emphasize a multi-process collaboration between the relationship, only when one of the process actively abandons the execution, the other can get execution, so in a moment, there is only one in a number of processes running.
4. Since there is only one running on multiple processes, access to the critical section does not need to be locked, and the multithreading situation must be locked.
5. Multi-threaded programs are not controllable because they have multiple control flows, and the execution of multiple threads is defined by the developer and therefore controllable.

The process of Lua is asymmetric (asymmetric coroutines), which means "suspending an executing synergistic function" and "making a function of a suspended coprocessor execute again" is different.

Some languages use symmetric collaboration (symmetric coroutines), which is responsible for "state switching between execution and suspend" using the same function.

non-nested Lua function

non-nested Lua functions (created loadfile by, loadstring or) is created sharing the environment of the load creating thread.

non-nested LUA functions does not have a specific example of what kind of function, just said by LoadFile loadstring and load, can be understood as a script file corresponding to an anonymous function.

These functions inherit the environment of the creator thread.

Environments associated with threads is called global environments. They is used as the default environment for threads and non-nested Lua functions created by the thread and can is Directl y accessed by C code (see§3.3).

Thread-related environments are called global environments, and when a thread creates a thread or non-nested a LUA function, the default environment of the creator inherits the environment of the creator thread.

Therefore, the non-nested LUA functions also has a global environment.

For require statements, invoking a script case, require is actually equivalent to the local f=loadfile (filename); F ()

The entire script corresponding to the anonymous function, the creator thread has the same environment, the creator thread through the Require method load, query loader, find the LUA script loader:

static int Loader_lua (Lua_state *l) {
const char *filename;
const char *name = lual_checkstring (L, 1);
filename = FindFile (L, Name, "path");
if (filename = = NULL) return 1; /* Library not found on this path */
if (lual_loadfile(L, filename)! = 0)
Loaderror (L, filename);
return 1; /* Library loaded successfully */
}

The environment for the Require function is _g

The implementation of the Require function is abbreviated as the filename script is created as the chunk corresponding anonymous function f, and F inherits the require environment by default _g

function require (filename)

If Package.loaded[filename] Then

return Package.loaded[filename]

End

Local F = assert (LoadFile (filename))

return F ()

End

Of course, if there is a module statement in the filename script, the environment of the anonymous function is overwritten.

This can be verified by the script given in this article.

Main.lua


Local module_mediator = require ("Module_mediator")

Var_caller = 55

Local function printtable (TBL)

For k,v in pairs (TBL) do
Print ("kay="): ToString (k): "Value=". ToString (v))
End

End


Print ("-----------module_mediator------------------")

PrintTable (Module_mediator)


Print ("-----------_g------------------")

PrintTable (_g)

Module_mediator.lua

Local require = require
Local setmetatable = setmetatable
Local setfenv = setfenv
Local getfenv = getfenv
Local ToString = ToString
Local print = Print

Module ("Module_mediator", Package.seeall)


Var_mediator = 77

--[[

Local require_env = {var_mediator=33}
Setmetatable (require_env, {__index=_g})

Setfenv (Require, require_env)
]]


Local require_env = getfenv (Require)

Local function printtable (TBL)

For k,v in pairs (TBL) do
Print ("kay="): ToString (k): "Value=". ToString (v))
End

End

Print ("require_env =": ToString (require_env))

Print ("-----------before require env------------------")

PrintTable (require_env)

Print ("-----------after require env------------------")


Local module_test = require ("Module_test")

Module_test.lua (Add and remove module, compare the results of getfenv (1) and getfenv (2) in this script:

Remove module, print:

Getfenv (1) =table:005d2658//Module_test.lua anonymous function environment
Getfenv (1) metatable=nil
Getfenv (2) =table:005d2658//Require environment, _g

Kay=_g value=table:005d2658

Add Module, Print:

Getfenv (1) =table:00773c68//Module_test.lua anonymous function environment

Getfenv (1) metatable=nil
Getfenv (2) =table:00252658//Require environment, _g

Kay=_g value=table:00252658

--module (..., package.seeall)

Local print = Print
Local getfenv = getfenv
Local ToString = ToString
Local getmetatable = getmetatable
Local pairs = Pairs

Module ("Module_test")


Local function printtable (TBL)

For k,v in pairs (TBL) do
Print ("kay="): ToString (k): "Value=". ToString (v))
End

End


Varone = 1

Local strkey = "Vartwo"


--This module environment
Local env = getfenv (1)

Env[strkey] = 2

Print ("vartwo="): Vartwo)

Print ("getfenv (1) =": ToString ((getfenv (1)))

Print ("getfenv (1) metatable="): ToString (Getmetatable (getfenv (1)))

If Getmetatable (getfenv (1)) Then
Print ("---------------before Getmetatable (getfenv (1))-------------")
PrintTable (Getmetatable (getfenv (1)))
Print ("---------------after Getmetatable (getfenv (1))-------------")
End

--the environment in which this module is called
Local Env_caller = getfenv (2)

env["Env_caller"] = Env_caller

Print ("getfenv (2) =": ToString (Getfenv (2)))

Print ("---------------before Env_caller-------------")
PrintTable (Env_caller)
Print ("---------------after Env_caller-------------")

Script files with chunk and anonymous functions

http://www.lua.org/manual/5.1/manual.html#2.11

The unit of execution of Lua is called a chunk. A chunk is simply a sequence of statements and which is executed sequentially. Each statement can is optionally followed by a semicolon:

Chunk:: = {stat ['; ′]}

There is no empty statements and thus "is not ;; legal.

The execution unit of LUA is chunk, and chunk is composed of a series of statements.

Lua handles a chunk as the body of a anonymous function with a variable number of arguments (see§2.5.9). As such, chunks can define local variables, receive arguments, and return values.

LUA treats a chunk as an anonymous function with a series of incoming arguments.

Therefore, chunk can define local variables, accept parameters, and return values.

A Chunk can is stored in a file or in a string inside the host program. To execute a chunk, Lua first pre-compiles the chunk into instructions for a vsan, and then it executes the COM Piled code with a interpreter for the virtual machine.

There are two forms of chunk, a file or a string.

Executing the chunk requires that the chunk be compiled into a directive, which is a virtual machine directive, then executes the compiled code, using the virtual machine interpreter.

Chunks can also is pre-compiled into binary form; See program for luac details. Programs in source and compiled forms is interchangeable; Lua automatically detects the file type and acts accordingly.

Chunk can be pre-compiled into binary form, with details participating in LUAC.

The source code and compilation form are interchangeable. LUA will automatically detect, file types, and perform response actions.

If it is a compiled file, LUA is no longer compiled, executed directly, and if it is not compiled, LUA will compile and execute it first.

Lua require dofile loadfile differences

http://blog.163.com/hbu_lijian/blog/static/126129153201422902256778/

1.dofile and LoadFile

Dofile is a primitive operation of Chunk as Lua runs code. Dofile is actually an auxiliary function. The function that really completes the function is loadfile; unlike Dofile, LoadFile compiles the code into an intermediate code and returns the compiled chunk as a function without executing the code, and LoadFile does not throw an error message but returns an error generation. We can define dofile like this:

function dofile (filename)

Local F = assert (LoadFile (filename))

return F ()

End

3.require and Dofile

。 Roughly speaking, require and dofile complete the same function but have two different points:

1. Require will search for directory loading files

2. Require will determine if the file has been loaded to avoid repeatedly loading the same file. Because of these features, require is a better function for loading libraries in Lua.

Nested Lua Luafunction

Nested LUA functions is created sharing the environment of the creating Lua function.

The nested LUA function shares the creator's environment.

What is a nested LUA function? There is no official definition.

Http://lua-users.org/wiki/LuaScopingDiscussion

Here's a discussion of the scope of nested functions, the use of function curry, which is nested in the SUM function:

function Addn (x)  function sum (y)    return x+y  end  return Sumendprint ((ADDN (3)) (1))
Interpreting nested function environments by sample example

Getfenvtest.lua

Local getfenv = getfenv
Local print = Print

Module ("Getfenvtest")


Var_test = 1


function test ()

Local env = getfenv (1)
Print ("var_test="): env["Var_test"])

Local Env_caller = getfenv (2)
Print ("env_caller[var_test]="): env_caller["Var_test"])
End


Test ()

Getfenv_main.lua

Var_test = 100

Local Testmodule = require ("Getfenvtest")


Local function printtable (TBL)

For k,v in pairs (TBL) do
Print ("kay="): ToString (k): "Value=". ToString (v))
End

End


Print ("--------before test func env------")
PrintTable (Getfenv (testmodule.test))
Print ("--------after test func env------")


function Mediator ()

Testmodule.test ()

End

Local env = {}
Env.testmodule = Testmodule
Env.mediatorflag = True
Env.var_test = 55

Setfenv (mediator, env)

Mediator ()

Print:

Call test Print in Var_test=1//Getfenv_test.lua, stating that the test function inherits the anonymous function environment of this script
Env_caller[var_test]=1///Getfenv_test.lua call Test Print, this script's anonymous function calls this function, so getfenv (2) in the function returns the environment of this script anonymous function


--------before test func env------//print indicates that, although used in the invoked script, the test function environment, or the environment in which it was created, is the module environment in Getenvtest.lua.
Kay=_name Value=getfenvtest
Kay=_package value=
Kay=test value=function:00539898
Kay=_m value=table:00539168
Kay=var_test value=1
--------after test func env------
Var_test=1//Although used in the invoked script, the environment that GETFENV obtains is still the environment of the module in Getfenvtest.lua, which is not related to the call point.
ENV_CALLER[VAR_TEST]=55//used in the called Script, getfenv (2) Gets the environment that invokes the script.
>exit code:0

An interesting environmental change experiment

Say a smart person, can according to the environment to speak different words, see the Americans, said the United States is a great country, see the Chinese, China is a great country, secretly no foreigners, said Mycountry is a great country.

First define the smart person to use the module construct for Wiseman.lua.

One of the key functions is makeenvdependfunc, which converts a normal function into a function that judges the environment.

The implementation principle is to transform the dependent environment of this function setfenv, when judging the called Scene getfenv (2), if present, the overriding environment is {}

With the metatable of this {} set to __index=function () end, the body of the function looks for getfenv (2) and then looks for getfenv (1).



Module ("Wiseman", Package.seeall)


Country = "My Country"


Local function Makeenvdependfunc (f)
Local oldfenv = Getfenv (f)

--ke name workspace gallium € chain chalk crypto env
Local envtbl = {}

Table.insert (ENVTBL, oldfenv)

   -Environment, and Isprior
    local addnewenv = function (env, isprior)
&nb sp;       if Isprior then
             Table.insert (ENVTBL, 1, env)
        Else
             Table.insert (ENVTBL, env)
         End
    end

    Local deletenewenv = function (targetenv)
        for I, Env in Ipairs (ENVTBL) do
            if targetenv = = env Then
                table.remove (Envtbl, I)
            End
         End
    end

Local INDEXENVTBL = function (env, key)
For i,env in Ipairs (ENVTBL) do
Local val = Env[key]
If Val Then
Return Val
End
End

return Nil
End

Local envmetatable = {__INDEX=INDEXENVTBL}
Local newfenv = {}
Setmetatable (newfenv, envmetatable)


Local fwrapper = function ()
Addnewenv (Getfenv (2), true)

Setfenv (f, newfenv)

Local ret = f ()

Deletenewenv (Getfenv (2))

Setfenv (f, oldfenv)

return ret
End

Return Fwrapper
End

--[[
function SayHello ()
Local env = getfenv (1)

Local Country_senario = Country

Local Env_caller = getfenv (2)
If Env_caller and Env_caller.country then
Country_senario = Env_caller.country
End


Print (Country_senario: "is a great country!")
End
]]

--Shu yukata 椂 country http Bibi ionizing buttons Andychia izotope module 锛? My Country
function sayhello_naive ()
Print (Country: "is a great country!")
End

SayHello = Makeenvdependfunc (sayhello_naive)

China.lua

Module ("China")

Country = "China"

function Callperson (Wiseman)
Wiseman. SayHello ()
End

American.lua


Module ("American")

Country = "American"

function Callperson (Wiseman)
Wiseman. SayHello ()
End

Keynote script Actionbycountry.lua


Local Wiseman = require ("Wiseman")


Local Chinese = require ("China")
Chinese. Callperson (Wiseman)

Local American = require ("American")
American. Callperson (Wiseman)


Wiseman. SayHello ()

Print:

>lua-e "Io.stdout:setvbuf ' No '" "Actionbycountry.lua"
China is a great country!
American is a great country!
My Country is a great country!
>exit code:0

The experimental script is as follows:

Https://github.com/fanqingsong/code-snippet/tree/master/lua/envtest

LUA Environment Exploration

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.