Lua code compilation

简介:
Lua 虽然是脚本解释语言, 在运行前需要预编译, 同时lua还支持代码预加载操作, 预编译操作等. 
在lua代码中  1. 使用load可以将文本转换成匿名函数,  2. 使用loadfile可以将外部文件转换成匿名函数. 3. 匿名函数可以赋予给一个变量然后调用, 或者直接使用()调用.
> a=1
> load("a=a+1 print(a)") ()
2
> f=load("a=a+1 print(a)")
> f()
3


load("a = a+1")
效果"等同"于
function () a = a+1 end

但实际上是有差别的,  1. load的效率远低于直接定义函数,  2. 另外, LOAD是有全局环境.
例如 : 
> do 
>> a = 100
>> local a = 1
>> f1 = function () a=a+1 print("1:" .. a) end
>> f1()
>> f2 = load("a=a+1 print(a)")
>> f2()
>> end
1:2  -- f1输出本地变量的值
101  -- f2输出全局变量的值


注意, load和loadfile期望文本为chunk内容, 如果是表达式的话, 可在表达式前添加return返回表达式的值. 
例如 : 
> f = load("a")
> print (f)
nil
> f()
stdin:1: attempt to call global 'f' (a nil value)
stack traceback:
        stdin:1: in main chunk
        [C]: in ?
改成 : 
> f = load("return a")  -- 返回表达式的值
> f()
> print(f())
nil


load和loadfile只是预加载代码, 并不会执行它, 只有执行了这个匿名函数后, 里面的代码才会得以执行. 
例如 : 
> f1 = load("f2 = function() a=99 print(a) end")
> f2()  -- 直接调用f2是不行的, 因为f1还没有执行.
stdin:1: attempt to call global 'f2' (a nil value)
stack traceback:
        stdin:1: in main chunk
        [C]: in ?
> f1()  -- f1被调用后, f2函数就存在了.
> f2()
99
> f3 = load("b=0")  -- b的定义同样要在f3函数调用后才会被执行
> print(b)
nil
> f3()
> print(b)
0

load和loadfile不检查文本的内容, 如果非法的话, 返回nil, 同时输出错误信息.
> print(load("err"))
nil     [string "err"]:1: syntax error near <eof>
> f = load("err")
> print(f)
nil

使用assert函数可以判断load和loadfile加载的内容是否正确(是否为nil), 如果为nil的话, 返回错误.
详见末尾assert的介绍.

> assert( load("err") )
stdin:1: [string "err"]:1: syntax error near <eof>
stack traceback:
        [C]: in function 'assert'
        stdin:1: in main chunk
        [C]: in ?

如果正确则返回参数值(匿名函数)
> f = assert( load("a=1 print(a)") )
> print(f)
function: 0x204eae0
> f()
1


> assert(nil)
stdin:1: assertion failed!
stack traceback:
        [C]: in function 'assert'
        stdin:1: in main chunk
        [C]: in ?
> assert(nil,"nihao")
stdin:1: nihao
stack traceback:
        [C]: in function 'assert'
        stdin:1: in main chunk
        [C]: in ?
> = assert(1,"nihao")
1       nihao
> a = assert(1,"nihao")
> print(a)
1


dofile是对loadfile封装后调用这个匿名函数 : 
function dofile (filename)
  local f = assert(loadfile(filename))
  return f()
end


> do
>> print ("enter function to be plotted (with variable 'x'):")
>> local l = io.read()
>> local f = assert(load("local x = ...; return " .. l))
>> for i=1,20 do
>>   print( string.rep("*", f(i)) )
>> end
>> end
enter function to be plotted (with variable 'x'):
x  -- 输入x
*
**
***
****
*****
******
*******
********
*********
**********
***********
************
*************
**************
***************
****************
*****************
******************
*******************
********************

string.rep($1, $2) 将$1复制$2遍. 如string.rep("*", 10) 复制星号10遍.

load可以使用reader函数作为参数, 从reader函数读取输入, 直到输入为nil.
例如load(io.lines(filename, "*L"))
这里的io.lines(filename, "*L") 返回一个reader函数, 调用这个函数从文件中每次读取1行.
load使用reader函数作为参数时, 从reader输入直到nil.
所以 load(io.lines(filename, "*L")) 和 loadfile("filename")效果是一样的.

参考 : 

load (ld [, source [, mode [, env]]])

Loads a chunk.

If ld is a string, the chunk is this string. If ld is a function, load calls it repeatedly to get the chunk pieces. Each call to ld must return a string that concatenates with previous results. A return of an empty string, nil, or no value signals the end of the chunk.

If there are no syntactic errors, returns the compiled chunk as a function; otherwise, returns nil plus the error message.

If the resulting function has upvalues, the first upvalue is set to the value of env, if that parameter is given, or to the value of the global environment. (When you load a main chunk, the resulting function will always have exactly one upvalue, the _ENV variable (see §2.2). When you load a binary chunk created from a function (see string.dump), the resulting function can have arbitrary upvalues.)

source is used as the source of the chunk for error messages and debug information (see §4.9). When absent, it defaults to ld, if ld is a string, or to "=(load)" otherwise.

The string mode controls whether the chunk can be text or binary (that is, a precompiled chunk). It may be the string "b" (only binary chunks), "t" (only text chunks), or "bt" (both binary and text). The default is "bt".

loadfile ([filename [, mode [, env]]])

Similar to load, but gets the chunk from file filename or from the standard input, if no file name is given.

assert (v [, message])

Issues an error when the value of its argument  v  is false (i.e.,  nil  or  false ); otherwise, returns all its arguments.  message  is an error message; when absent, it defaults to "assertion failed!"
目录
相关文章
|
存储 NoSQL Redis
Redis的Lua脚本有什么作用?
Redis Lua脚本用于减少网络开销、实现原子操作及扩展指令集。它能合并操作降低网络延迟,保证原子性,替代不支持回滚的事务。通过脚本,代码复用率提高,且可自定义指令,如实现分布式锁,增强Redis功能和灵活性。
657 1
|
缓存 NoSQL 搜索推荐
【📕分布式锁通关指南 03】通过Lua脚本保证redis操作的原子性
本文介绍了如何通过Lua脚本在Redis中实现分布式锁的原子性操作,避免并发问题。首先讲解了Lua脚本的基本概念及其在Redis中的使用方法,包括通过`eval`指令执行Lua脚本和通过`script load`指令缓存脚本。接着详细展示了如何用Lua脚本实现加锁、解锁及可重入锁的功能,确保同一线程可以多次获取锁而不发生死锁。最后,通过代码示例演示了如何在实际业务中调用这些Lua脚本,确保锁操作的原子性和安全性。
765 6
【📕分布式锁通关指南 03】通过Lua脚本保证redis操作的原子性
|
消息中间件 NoSQL Java
Redis系列学习文章分享---第六篇(Redis实战篇--Redis分布式锁+实现思路+误删问题+原子性+lua脚本+Redisson功能介绍+可重入锁+WatchDog机制+multiLock)
Redis系列学习文章分享---第六篇(Redis实战篇--Redis分布式锁+实现思路+误删问题+原子性+lua脚本+Redisson功能介绍+可重入锁+WatchDog机制+multiLock)
766 0
|
NoSQL Redis 数据库
Redis 功能扩展 Lua 脚本 对Redis扩展 eval redis.call redis.pcall
通过本文的介绍,我们详细讲解了 Lua 脚本在 Redis 中的作用、`eval` 命令的使用方法以及 `redis.call` 和 `redis.pcall` 的区别和用法。通过合理使用 Lua 脚本,可以实现复杂的业务逻辑,确保操作的原子性,并减少网络开销,从而提高系统的性能和可靠性。
966 13
|
监控 安全
公司用什么软件监控电脑:Lua 脚本在监控软件扩展功能的应用
在企业环境中,电脑监控软件对保障信息安全、提升效率至关重要。Lua 脚本在此类软件中用于扩展功能,如收集系统信息、监控软件使用时长及文件操作,向指定服务器发送数据,支持企业管理和运营。
265 6
|
缓存 分布式计算 NoSQL
大数据-43 Redis 功能扩展 Lua 脚本 对Redis扩展 eval redis.call redis.pcall
大数据-43 Redis 功能扩展 Lua 脚本 对Redis扩展 eval redis.call redis.pcall
233 2
|
存储 JSON Ubuntu
如何使用 Lua 脚本进行更复杂的网络请求,比如 POST 请求?
如何使用 Lua 脚本进行更复杂的网络请求,比如 POST 请求?