遞迴資料類型

lua-users home
wiki

函數式程式語言藉由提供積資料型別和和資料型別,讓遞迴變得非常容易。這些資料型別會內建在像 Haskell 和 ML 的語言中,而且可以像 EOPL 一樣,連同聰明的巨集程式加入 Scheme[1] 中。如果 Scheme 可以做到,Lua 也可以 :-)

假設您想要表示為標示節點和編號葉子的樹。

要建立此資料結構,則需要為每個變體節點建立一個建立函式:InteriorNodeLeafNode。且當遍歷資料結構時,您需要判斷會的陳述式來處理不同資料。函式 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 · 喜好設定
編輯 · 歷史記錄
最後編輯時間為 2013 年 7 月 10 日,下午 7:50,格林威治時間 (相異)