递归数据类型

lua-users home
wiki

函数式编程语言通过提供积类型和和类型(product and sum data types)使得递归非常容易。这些类型内置于 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。


RecentChanges · preferences
编辑 · 历史
最后编辑于 2013年7月10日 下午1:50 GMT (差异)