1、编译

  前面介绍的,dofile是一个运行lua代码块的基本操作,实际上它是一个辅助函数。

loadfile才真正做了核心的工作。dofile(打开文件,执行里面的代码块)和loadfile(从文件或stdin中获取代码块)实际不运行代码,

只是编译,然后将结果作为一个函数返回。loadfile与dofile不同的 是它不会引发错误,只是返回错误值并不处理错误。

一般dofile定义:

function dofile(filename)
local f = assert(loadfile(filename)) --如果loadfile失败,assert就会引发一条错误
return f()
end

通常,如果我们要多次运行一个文件,只需用loadfile一次,再多次调用它的返回结果就可以了。

相对于dofile来说,它只编译一次,开销就小得多。

与loadfile类似的函数load,它是从字符串中读取代码,而不是文件。

f = load("i = i + 1")

f变成了一个函数,每次调用就执行"i = i + 1"

i =
f();print(i) --> 1
f();print(i) --> 2

使用load的时候要小心,它的开销大,并且会返回一些难以理解的代码。

如果你想塑造一个便捷但粗糙的dostring(load and run a chunk):

load(s)()   -- 有语法错误,load返回nil就会报错

--优化的版本

assert(load(s))()

一般将load用于字面字符串是没有意义的:

f = load("i = i + 1")

--基本上等价于

f = function() i = i +  end

但是第二行要快的多,因为它只编译了一次,而第一行每次调用load都要重新编译。

因为load编译的时候不涉及词法域,所以两者还是有区别的:

i  =
local i =
g = load("i = i + 1 ; print(i)") -- 字符串,访问的是全局 i
f = function() i = i + ;print(i) end -- 函数块,访问的是local i
g() --> 33
f() --> 1

函数 f 访问的是local  i

函数 g 访问的是全局  i

因为load总是在全局环境去编译代码块。

load最典型的用处是执行外部代码,那些位于程序之外的代码( 就像加载配置文件config一样,之前疑惑的地方 )。

有很多地方需要用户自定义函数,就要求输入函数代码,然后调用load去求值。

如果要对一个表达式求值,则必须在其之前添加return,这样才能构成一条语句,返回表达式的值:

print"enter your expression:"        -- 输入 1 + 2
local r = io.read()
local func = assert(load("return " .. r))
print("the value is " .. func())       -- the value is 3

因为load返回的是函数,所有可以多次调用:

print "enter function to be plotted(with variable 'x'):"  --输入一个数字,因为string.rep(第二个参数要数字,如果输入a或者b之类的 返回值为nil)
local r = io.read()
local f = assert(load("return " .. r))
for i = , do
x = i
print(string.rep("*",f()))
end

loadfile的实质也是调用load,load接收一个"读取器函数--reader function",并在内部调用它来获取程序块:

它可以分几次返回一个程序块,load会反复调用它,直到返回nil。

下面的例子就等于loadfile:

f = load(io.lines(filename,"*L")) --每次调用io.lines,都返回一个函数

--下面的代码更高效

f = load(io.lines(filename,))

Lua把这些独立的代码块当作匿名函数的函数体。比如load(“a = 1”)等于:

function (...) a =  end

代码块也可以声明local变量:

f = load("local a = 10; print(a+20)")
f() --> 30

有了这些特点:可以重写上面的例子,避免用全局变量:

print "enter function to be plotted(with variable 'x'):"
local r = io.read()
local f = assert(load("local x = ...;return " .. r)) --把x声明为local变量,当调用f(i)时,...就变成了参数i。
for i = , do
print(string.rep("*",f(i)))
end

load不会引发错误,在错误情况中,load会返回nil及一条错误消息。

print (load("i i"))
--> nil [string "i i"]:1: syntax error near 'i'

此外,这些函数不会有其他副作用。

有一个误解,认为加载了一块代码,就定义了其中的函数。

在Lua中函数定义是一种赋值操作,也就是说,它们是在运行时才完成的操作:

一个foo.lua:

--file 'foo.lua'
function foo(x)
print(x)
end

运行它:

f = loadfile("foo.lua")

运行之后,foo函数只是编译,还没有被定义。为了定义它,必须运行这个chunk:

print(foo)        --> nil
f() -- defines 'foo',即运行它
foo("ok") --> ok

此外,若需要在一个商业品质的程序中执行外部代码,还要处理加载程序块时报告的错误。

如果代码是不可信的,还要在一个保护环境下执行。

chapter8_1 编译执行和错误的更多相关文章

  1. Step By Step(Lua编译执行与错误)

    Step By Step(Lua编译执行与错误) 1. 编译:    Lua中提供了dofile函数,它是一种内置的操作,用于运行Lua代码块.但实际上dofile只是一个辅助函数,loadfile才 ...

  2. C#编译执行过程

    前言 大家好,我是卫斯理(Wesley).喜欢武侠的朋友可能知道小说中也有个卫斯理,他是位冒险家,财力充沛,极富冒险精神,并且有着超强的好奇心,对奇异的事情总有"打破沙锅问到底"的 ...

  3. JAVA 文件编译执行与虚拟机(JVM)简单介绍

    详见:http://blog.yemou.net/article/query/info/tytfjhfascvhzxcytpo3 java程序的内存分配 JAVA 文件编译执行与虚拟机(JVM)介绍 ...

  4. 超具体Windows版本号编译执行React Native官方实例UIExplorer项目(多图慎入)

    ),React Native技术交流4群(458982758).请不要反复加群! 欢迎各位大牛,React Native技术爱好者加入交流!同一时候博客右側欢迎微信扫描关注订阅号,移动技术干货,精彩文 ...

  5. 前端必备:FastStoneCapture 和 Licecap &&& mingw c++ 编译执行

    端必备:FastStoneCapture 和 Licecap FastStoneCapture这个软件非常小,只有2M多,并且其功能很强大,包括截图,录制视频,量尺,取色等等,对于前端工程师绝对是必备 ...

  6. 编译 & 执行 C++ 程序

    编译 & 执行 C++ 程序接下来让我们看看如何把源代码保存在一个文件中,以及如何编译并运行它.下面是简单的步骤: 打开一个文本编辑器,添加上述代码.保存文件为 hello.cpp.打开命令提 ...

  7. TeamCity编译执行selenium上传窗口脚本缺陷

    2015-07-04 18:05 编写本文 TeamCity编译selenium脚本,对于上传窗口处理只支持sendKeys的使用,不支持模拟人为按下Enter键和使用autoIt等操作,即使本地调试 ...

  8. Java解释执行和编译执行

    以前有句话说:“Java是解释执行的 ” .现在看来确实不是很准确,至于原因,在此简略解释: 首先,我们先解释一下在Java中解释执行和编译执行的区别. 解释执行:将编译好的字节码一行一行地翻译为机器 ...

  9. JNI之——在cmd命令行下编译执行C/C++源文件

    转载请注明出处:http://blog.csdn.net/l1028386804/article/details/46604269 一直用java来敲代码,java配置好jre路径之后.在cmd下编译 ...

随机推荐

  1. 敏捷开发(十一)- Scrum Sprint评审会议

    本文主要是为了检测你对SCRUM 评审会议的了解和使用程度, 通过本文你可以检测一下     1.你们的SCRUM 评审会议的过程和步骤    2.SCRUM 评审会议的输出结果一.会议目的     ...

  2. jmeter命令行运行-单节点

    jmeter有自己的GUI页面,但是当线程数很多或者现在有很多的测试场景都是基于linux下进行压测,这时我们可以使用jmeter的命令行方式来执行测试,该篇文章介绍jmeter单节点命令运行方式. ...

  3. 《Javascript权威指南》

    <Javascript权威指南> chorme.safari中的input或textarea html超链接(a)详细讲解 html5新增及删除标签 html表格 图片加alt属性

  4. Scala内部类

    注意:Java内部类从属于外部类,而Scala内部类从属于对象(外部类的实例本身).

  5. JQuery笔记(三)选项卡

    通过jq封装的方法,可以更简单的制作一个选项卡 <!DOCTYPE html> <html lang="en"> <head> <meta ...

  6. SQLSERVER 的联接查询写法

    1.内连接 语法:[JOIN.INNER JOIN] 作用:两个表相连,加上ON匹配两个表的共同条件. 实例1: SELECT tb_o_i.* FROM tb_o_i INNER JOIN tb_o ...

  7. 通过字典给类的实体属性赋值生成url字符串

    private static Dictionary<string, string> SortedToDictionary(SortedDictionary<string, strin ...

  8. 使用SyncToy 同步两台机器上的文件夹

    @echo off echo 准备启动同步... net use \\WIN-AJH8QENQQGK "123456" /user:Administrator Z:\SyncToy ...

  9. Voting

    Voting time limit per test 1 second memory limit per test 256 megabytes input standard input output ...

  10. Arpa's loud Owf and Mehrdad's evil plan

    Arpa's loud Owf and Mehrdad's evil plan time limit per test 1 second memory limit per test 256 megab ...