记录模式

Hyp*_*eus 4 erlang design-patterns record

我正在学习二郎,我偶然发现了一些我无法理解的行为.拿这段代码.(我知道我正在编程的是现有的库,但正如我所说,我这样做是出于教育目的):

-module (codec).
-compile (export_all).
-record (node, {symbol, weight, order, left, right, parent} ).
-record (tree, {root, nodes} ).

highestOrderForWeight (Weight, Tree) ->
    lists:max ( [Node#node.order || Node <- Tree#tree.nodes, Node#node.weight == Weight] ).

swapMaybe (Node, Tree) ->
    case highestOrderForWeight (Node#node.weight, Tree) of
        Node#node.order -> pass; 
        Node#node.parent -> pass;
        Tree#tree.root -> pass;
        Partner -> io:format ("Swapping ~p with ~p.~n", [Node#node.order, Partner] )
    end.
Run Code Online (Sandbox Code Playgroud)

编译器对我的代码一无所知:

./so.erl:11: illegal pattern
./so.erl:12: illegal pattern
./so.erl:13: illegal pattern
error
Run Code Online (Sandbox Code Playgroud)

在模式中消化记录显然有些麻烦,因为当我将我的代码更改为这种笨拙的解决方案时,它编译得很好:

swapMaybe2 (Node, Tree) ->
    [Order, Parent, Root] = [Node#node.order, Node#node.parent, Tree#tree.root],
    case highestOrderForWeight (Node#node.weight, Tree) of
        Order -> pass; 
        Parent -> pass;
        Root -> pass;
        Partner -> io:format ("Swapping ~p with ~p.~n", [Node#node.order, Partner] )
    end.
Run Code Online (Sandbox Code Playgroud)

问题:

  • 如何访问模式中的记录字段?
  • 如果不可能这样做,为什么会这样呢?
  • 如果不可能这样做,解决这个问题的常见做法是什么?

hdi*_*ima 6

实际上,记录只是一个编译时的语法糖,您可以使用'E' 编译器选项查看实际的构造.例如,Node#node.order将替换为这样的东西:

case Node of
    {node,_,_rec0,_,_,_} ->
        rec0;
    _ ->
        error({badrecord,node})
end
Run Code Online (Sandbox Code Playgroud)

当然,当您尝试使用Node#node.order作为模式编译器报告illegal pattern此构造时.

您的swapMaybe功能可以像这样重写:

swapMaybe(#node{order=Order, parent=Parent}, Tree=#tree{root=Root}) ->
    case highestOrderForWeight (Weight, Tree) of
        Order -> pass; 
        Parent -> pass;
        Root -> pass;
        Partner -> io:format ("Swapping ~p with ~p.~n", [Order, Partner] )
    end.
Run Code Online (Sandbox Code Playgroud)