第一个例子
将Lua脚本作为一个小型的简化版的“数据库”,展现了如何简单高效的将这个“数据库”中的数据转化为网页显示。
-- "db.lua"文件中内容。
--[[ 这里看似是一张名为"entry"的表中存储了许多数据,
实际上在转化程序中这时一个名为"entry"的函数,
参数是下面这个存储了许多数据的"table"。
还记得"foo({})"与"foo{}"等同吗?]]
entry{
title = "Tecgraf",
org = "Computer Graphics Technology Group, PUC-Rio",
url = "http://www.tecgraf.puc-rio.br/",
contact = "Waldemar Celes",
description = [[
TeCGraf is the result of a partnership between PUC-Rio,
the Pontifical Catholic University of Rio de Janeiro,
and <A HREF="http://www.petrobras.com.br/">PETROBRAS</A>,
the Brazilian Oil Company.
TeCGraf is Lua's birthplace,
and the language has been used there since 1993.
Currently, more than thirty programmers in TeCGraf use
Lua regularly; they have written more than two hundred
thousand lines of code, distributed among dozens of
final products.]]
}
-- "main.lua"文件中内容。
function fwrite (fmt, ...)
-- 可变参数由"..."传递。
for i = 1, select('#', ...) do
arg[i] = select(i, ...) -- 这里select()返回了i之后所有的值,但多余的值被抛弃了。
end
return io.write(string.format(fmt, table.unpack(arg)))
end
function BEGIN()
io.write([[
<HTML>
<HEAD><TITLE>Projects using Lua</TITLE></HEAD>
<BODY BGCOLOR="#FFFFFF">
Here are brief descriptions of some projects around the
world that use <A HREF="home.html">Lua</A>.
<BR>
]])
end
function entry0 (o)
N=N + 1
local title = o.title or '(no title)'
fwrite('<LI><A HREF="#%d">%s</A>\n', N, title)
end
function entry1 (o)
N=N + 1
local title = o.title or o.org or 'org'
fwrite('<HR>\n<H3>\n')
local href = ''
if o.url then
href = string.format(' HREF="%s"', o.url)
end
fwrite('<A NAME="%d"%s>%s</A>\n', N, href, title)
if o.title and o.org then
fwrite('<BR>\n<SMALL><EM>%s</EM></SMALL>', o.org)
end
fwrite('\n</H3>\n')
if o.description then
fwrite('%s', string.gsub(o.description,
'\n\n\n*', '<P>\n'))
fwrite('<P>\n')
end
if o.email then
fwrite('Contact: <A HREF="mailto:%s">%s</A>\n',
o.email, o.contact or o.email)
elseif o.contact then
fwrite('Contact: %s\n', o.contact)
end
end
function END()
fwrite('</BODY></HTML>\n')
end
BEGIN()
N = 0
entry = entry0 -- 为"entry"赋值不同的逻辑,用不同的逻辑操作"db.lua"中的"table"。
fwrite('<UL>\n')
dofile('db.lua') -- 加载"db.lua"中的内容并执行。相当于调用"entry()",以"table"作为参数。
fwrite('</UL>\n')
N = 0
entry = entry1 -- 为"entry"赋值不同的逻辑,用不同的逻辑操作"db.lua"中的"table"。
dofile('db.lua') -- 加载"db.lua"中的内容并执行。相当于调用"entry()",以"table"作为参数。
END()
$ lua x.lua > test.html
第二个例子
是实现”Markov chain algorithm”。”Markov chain algorithm”就是满足一些值与另一些值之间的映射关系的值的序列。举个例子会更容易理解,
the more we try the more we do
这个就是个值(每个单词算作一个值)的序列,这个值的序列从左至右满足如下的映射关系,
[\n \n] = {"the", } -- 初始的默认值是"\n",所以"\n \n"之后跟着"the"。
[\n the] = {"more", } -- "\n the"之后跟着"more"。
[the more] = {"we", "we", } -- "the more"之后跟着"we"。因为出现了两个"the more",所以这里有两个"we"。
[more we] = {"try", "do", } -- "more we"之后跟着"try"或者"do"。
[we try] = {"the", } -- "we try"之后跟着"the"。
[try the] = {"more", } -- "try the"之后跟着"more"。
[we do] = {"\n", } -- "we do"之后跟着"\n"。
接下来的例子就是输出给定的值的序列的”Markov chain”,索引值限定为两个,
-- 返回一个"iterator"。每次被调用,从给定的值的序列中找出一个单词。
function allwords ()
local line = io.read() -- 输入给定的值的序列。
local pos = 1 -- 值的序列中搜索到了哪里。
return function () -- "iterator function"。
while line do
-- 从给定的值的序列中找出一个单词,返回单词的起始和终止位置。
local s, e = string.find(line, "%w+", pos)
if s then -- 找到了一个单词。
pos = e + 1 -- 更新搜索位置。
return string.sub(line, s, e) -- 返回找到的单词。
else -- 没找到单词。
line = io.read() -- 读取下一行。
pos = 1 -- 值的序列中搜索位置重置。
end
end
return nil
end
end
-- 将两个索引值组合成为一个索引。
function prefix (w1, w2)
return w1 .. ' ' .. w2
end
-- 将索引与值的映射存入"statetab"。
function insert (index, value)
if not statetab[index] then
-- 一个索引可能对应多个值(["more we"] = {"try", "do"}),所以"table"存储。
statetab[index] = {}
end
table.insert(statetab[index], value)
end
local N = 2 -- 索引值限定为两个。
local MAXGEN = 10000 -- 最大产生的结果数量。
local NOWORD = "\\n" -- 默认的索引值是"\n"。
-- 创建映射关系并存储。
statetab = {} -- 存储映射关系的"table"。
local w1, w2 = NOWORD, NOWORD -- 初始的两个索引值都是"\n"。
for w in allwords() do -- 产生索引值。
insert(prefix(w1, w2), w) -- 存储映射关系。
w1 = w2; w2 = w; -- 向后依次更替索引值。
end
insert(prefix(w1, w2), NOWORD) -- 存储最后一个映射关系([we do] = {"\n", })。
-- 打印"statetab"中的内容。
for k, v in pairs(statetab) do
io.write(string.format("[%s] = {", k))
for m, n in ipairs(v) do
io.write(string.format("\"%s\", ", n))
end
io.write("}\n")
end
--[[ 以初始索引在"statetab"中随机取值,
不断的以新的值与旧的索引值组合成为新的索引,再次在"statetab"中随机取值,
循环往复,打印出找打的值。]]
w1 = NOWORD; w2 = NOWORD -- 重新初始化索引值为默认的索引值。
for i = 1, MAXGEN do -- 最大结果数量为"MAXGEN"个。
local list = statetab[prefix(w1, w2)]
-- 产生随机数种子。
math.randomseed(tonumber(tostring(os.time()):reverse():sub(1, 6)))
--[[ 从"list"中随机选择一个元素,
比如[more we] = {"try", "do", }对应"try"和"do"两个元素,随机选择一个。]]
local r = math.random(#list) -- 生成随机数。
local nextword = list[r]
if nextword == NOWORD then -- 如果到了默认的索引值,就不再找了。
break
end
io.write(nextword, " ")
w1 = w2; w2 = nextword -- 不断的以新的值与旧的索引值组合成为新的索引。
end
io.write("\n")
$ lua markov_chain.lua
the more we try the more we do
<Ctrl-D>