快速掌握Lua 5.3 —— 两个完整的例子

第一个例子

将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>

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值