递归数据类型

lua-users home
wiki

函数式编程语言通过提供乘积和求和数据类型,使递归变得非常容易。这些类型内置于 Haskell 和 ML 等语言中,并且可以通过像 EOPL[1] 中的巧妙宏添加到 Scheme 中。如果 Scheme 可以做到,Lua 也能做到 :-)

假设您想表示一个带有标记节点和编号叶子的树。

要构建这样的数据结构,您需要为每个节点变体创建一个构造函数:InteriorNodeLeafNode。在遍历数据结构时,您需要一个 switch 语句来对不同的数据执行不同的操作。函数 deftype[3] 从简单的规范中创建构造函数。函数 cases 返回一个切换函数,可用于遍历数据结构。

require'DefType'

deftype 'bintree' {
  'number';
  Node = {
    name ='string',
    left ='bintree',
    right='bintree',
  };
}

local function node(name, left, right)
  return Node{name=name, left=left, right=right}
end

local tree = node(
  'cow',
  node('rat', 1, 2),
  node('pig', node('dog', 3, 4), 5)
)

------------------------------------------------------------------------------

local leafsum
leafsum = cases 'bintree' {

  number = function(n) return n end;

  Node = function(node)
    return leafsum(node.left) + leafsum(node.right)
  end;
}

io.write('leaf sum = ', leafsum(tree), '\n\n')

------------------------------------------------------------------------------

local function indented(level, ...)
  io.write(string.rep('  ', level), unpack(arg))
end

local treewalki
treewalki = cases 'bintree' {

  number = function(n)
    io.write(' @LeafNode ', n, '\n')
  end;

  Node = function(node, level)
    local plus1 = level+1
    io.write(' {\n')
    indented(plus1, '@InteriorNode ', node.name, '\n')
    indented(plus1, '@left')
    treewalki(node.left, plus1)
    indented(plus1, '@right')
    treewalki(node.right, plus1)
    indented(level, '}\n')
  end;
}

local function treewalk(t)
  io.write('@Tree')
  treewalki(t, 0)
end

treewalk(tree)
此示例产生以下输出

leaf sum = 15

@Tree {
  @InteriorNode cow
  @left {
    @InteriorNode rat
    @left @LeafNode 1
    @right @LeafNode 2
  }
  @right {
    @InteriorNode pig
    @left {
      @InteriorNode dog
      @left @LeafNode 3
      @right @LeafNode 4
    }
    @right @LeafNode 5
  }
}

树形图由 Lout[2][fig1.lt] 生成。Ghostscript 用于将 EPS 转换为 JPG。


最近更改 · 偏好设置
编辑 · 历史记录
最后编辑于 2013 年 7 月 10 日下午 7:50 GMT (差异)