zoukankan      html  css  js  c++  java
  • lua学习笔记(十)

     

     
    模块与包
     使用require加载模块
        一个规范的模块应该返回一个table作为这个模块所有导出功能的集合
        lua里没通过任何强制性语法规则要求创建模块时反回一个table
        但最好这么做,因为大多lua的模块都是这么发布的
       --require的实现源代码
        function require(name)
            if not package.loaded[name] then
                local loader = findloader(name)
                if loader == nil then
                    error("unable to load module "..name)
                end
                package.loaded[name] = true
                local res = loader(name)
                if res ~= nil then
                    package.loaded[name] = res
                end
            end
            return package.loaded[name]
        end
        require的内部实现就是通过loadfile或loadlib来加载程序块
        所以加载模块就当相于把程序块看做一个函数
        然后使用模块的文件名作参数调用一次就加载完成了
        只要使用require加载过一次的模块就不会再重复加载了,除非手动把package.loaded[name]=nil
        已加载的模块记录在package.loaded的table里
        loader是一个加载器,它会从package.preload里找对应的加载函数来实施加载
        require"mod"会得到一个全局的mod变量
        local m = require"mod"可以重定义导入模块的名称
        require的加载路径如:
        ?;?.lua;c:windows?;/usr/local/lua/?/?.lua
        require会以模块名来替换所有"?",每个条目用";"隔开
        也就是说require只处理分号和问号
        require用于搜索lua文件的路径存放在变量package.path中
        当lua启动后便以环境变量LUA_PATH来初始化这个变量
        如果没有找到环境变量LUA_PATH就以编译时定义的一个默认常是值来初始化
        LUA_PATH里的";;"子串会替换成默认路径
        如果require找不到lua文件就会去找c程序库,路径放在package.cpath里用LUA_CPATH初始化
        在加载c程序库里如果模块名如a-b,则以b为模块加载
        如果一个模块名为mod.sub则认为sub是mod的子模块,在require时会使用配置好的分隔符替换"."
        如果mod.sub会替换为modsub这样就可以很容易的分目录放置了
     使用module创建模块
        手工写法
         --创建模块--------------------------------------------------------------------------------         --require会把文件名当参数传进来,用这个变量记下来就行了
          local modname = ...
     
          --创建一个local的table用于记录导出内容
          local _M = {}
     
          --导出的table就等于这个local的table
          _G[modname] = _M
     
          --有了这句就不用return _G[modname]给require了
          package.loaded[modname] = _M
     
          --设置本环境继承全局环境,不然连接print都不能用,
          --其实如果在模块中要用全局内容,可能赋给local变量然后使用
          setmatetable(_M, {__index = _G})
     
          --把这个local的table调成当前环境
          setfenv(1, _M)
     
          --模块内容 ------------------------------------------------------------------------------          --由于使用了环境,所以local根本就不会进入环境,也就不会导出了
          local function test001()
                print("test001")
          end
     
          --全局函数相当于_M.test002=function()end会导出
          function test002()
                print("test002")
          end
        内建module关键字
          --这一句把上面创建模块部分的代码都包括了,没有package.seeall就不继承全局环境                     module(...,package.seeall)
     
  • 相关阅读:
    获取成本
    销售订单跟踪成本
    装机
    这就是用战术上的勤奋掩盖战略上的懒惰
    CPA-计划(参考)
    大帝名言
    BZOJ 2100: [Usaco2010 Dec]Apple Delivery spfa
    BZOJ 2834: 回家的路 Dijkstra
    BZOJ 4070: [Apio2015]雅加达的摩天楼 根号分治+spfa
    BZOJ 4152: [AMPPZ2014]The Captain Dijkstra+贪心
  • 原文地址:https://www.cnblogs.com/lifesteven/p/4169406.html
Copyright © 2011-2022 走看看