[Lua Basics] Package package--module Development

Source: Internet
Author: User
Tags lua pack require

A package is a way to organize your code. many languages specialize in providing a mechanism for naming global variables, such as Modula's Modules,java and Perl's packages,c++ namespaces. Each mechanism has different rules for the visibility of the elements declared in the package and the use of some other details . But they all provide a mechanism to avoid problems with naming conflicts in different libraries . Each library creates its own namespace, and the names defined in this namespace do not interfere with the names defined in other namespaces.

LUA does not provide a clear mechanism to implement packages. However, the basic mechanisms that we provide through language are easy to achieve with him. The main idea is to use a table to describe the package like a standard library.

The obvious benefit of using tables to implement packages is that we can use packages like any other table, and we can use all the features provided by the language to bring a lot of convenience . In most languages, packages is not a first-class value (first-class values) (that is, they cannot be stored in variables, not as function arguments ...). As a result, these languages require special methods and techniques to achieve similar functionality. In Lua, although we have been using tables to implement Pachages, there are different ways to implement the package.

Vector3D = {}  --Package name  
function Vector3d.function1 ()  
... End  
function Vector3d.function2 () ...  
      if (Vector3d.function1 ()) then  
      ...  
      End  
End  

This defines a Vector3D package that, when opened with the require language, can use both Vector3d.function1 and Vector3d.function2 functions.

This is the most direct and best understanding of a package definition, but there are some drawbacks. This drawback is mainly reflected in the package implementation process. Can be seen, even in

The Function1 () function in Vector3d.function2 () must also be fully prefixed with the vector3d package name, otherwise the function call cannot be made . The package author is a little bit tired, but the user is fine. special attention to the final return Vector3D statement , after which the caller can rename the package as follows:

MyPackage =  require "Vector3D"  

Method Two: Use local functions to define all of the package functions, and then put the functions that need to be exposed directly into the package at the end of the package. The code looks like this:

Vector3D = {}  --Package name  
local function function1 ()  
... End  
 
local function function2 () ...  
      if (function1 ()) then  
      ...  
      End  
End  
Vector3D = {function1 = functoin1,   
function2function2 = function2  
}  

The last part that is assigned to the package is the part that exposes the required interface. The benefit of this is that functions that do not need to be exposed can be completely hidden (all local functions), and the package's internal functions are no longer required to differentiate between the package names when they are called from each other; You can optionally rename the interface name that is exposed by the package as needed. The disadvantage of this approach is that the definition of the time required to write on the local, this is not a disadvantage to see you--. for me personally, you can use local n = {} to save data and define private variables and functions . Can clearly distinguish between the interface and the private definition, the name of the public interface can also be arbitrarily changed, which means that the internal implementation can be arbitrarily replaced without affecting the external caller.

no matter what method you use to define the package, it is intended to logically better plan the code hierarchy. The table mechanism in LUA is indeed a dynamic mechanism. The package relies on this implementation, and LUA itself has some mechanisms that depend on tables (such as global variables in the _g table)

How to "unpack" the code snippet of the package is a great way to show the power of the table (the package is also a logical product built on the table). The idea of unpacking the package is to put the name that is exposed in all the package into the _g table. That is, let Package.a () into _G.A (_g in general do not need to write, the default reference)

function OpenPackage (NS) for  
      n,v in pairs (ns)   
     do  
            _g[n] = v  
     End  

Implementation Method

A package is typically defined as a module function within a LUA file. The module also defines a new package's function environment so that the global variables defined in this package are in this environment, not in the environment that uses the package's functions. Understanding this is critical. In the previous code example, "Module (..., package.seeall)" means defining a package whose name is the same as the name of the file that defines the package (except for the filename suffix, in the previous code, "Mypack"). And in the function environment of the package can access the function environment using the package (for example, the implementation of the package uses print, this variable is not defined in the package, but is defined in the external environment using the package).

How to use

The Require function is typically used to import a package, and the package to be imported must be placed on the package path (PackagePath). Package paths can be set by Package.path or environment variables. In general, the current work path is always in the package path.

--testp.lua:
pack = require "Mypack"--Import Package
print (ver or "No ver defined!")
Print (Pack.ver)
print (Afuninmypack or
"No afuninmypack defined!")
Pack.afuninmypack ()
print (Afuncfrommypack or
"No afuncfrommypack defined!")
Afuncfrommypack ()

--mypack.lua:
module (..., package.seeall)--Define package
ver = "0.1 Alpha"
function Afuninmypack ()
print ("hello!")
End
_g.afuncfrommypack =
afuninmypack

performs Testp.lua output:
No ver defined!
0.1 Alpha
No afuninmypack defined!
Hello!
FUNCTION:003CBFC0
hello!
how modules are defined

There are two ways to define the module, the old one, for Lua 5.0 and the earlier version 5.1, and the new way to support the new release of Lua5.1 and version 5.2.
the old way declare a package by module ("...", Package.seeall) . This is the way to see many of GitHub's earlier open source projects, but it is not recommended to use this way.

Defined:

--Oldmodule.lua
module ("Oldmodule", Package.seeall)
function foo ()
  print ("Oldmodule.foo called")
End
use:
Require "Oldmodule"
Oldmodule.foo ()
1.module () The first parameter is the module name, and if not set, the file name is used by default. 2. The second parameter Package.seeall, by default after a module () is defined, the previously defined global variables are not available, including the print function, if you want to make the previous global variables visible, The parameter package.seeall must be added when the module is defined. Specific reference cloud Wind this article Package.seeall: Sets a meta-table for module, the value of the __index field for this meta-table is the global environment _g. So module can access the global environment.
There are two reasons why the module ("...", Package.seeall) is no longer recommended in this way.
1.package.seeall this way destroys the high-cohesion of the module, which originally introduced Oldmodule to call its foo () function, but it can read and write global properties, such as Oldmodule.os. 2. The second flaw is caused by the side-effect of the module function, which pollutes global environment variables. The module ("Hello.world") creates a Hello table and injects the table into the global environment variable so that modules that do not want to reference it can also invoke the Hello module method. The New Way implement a module by return table
--newmodule.lua
Local newmodule = {}
function Newmodule.foo ()
  print ("Newmodule.foo called")
end
return Newmodule
Use
Local new = require "Newmodule"
New.foo ()
because there is no global variable and the module keyword, the reference must be assigned to a variable

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.