我想知道如何通常实现模式匹配。例如在Erlang中你认为它是在字节码级实现的(它有一个字节码,以便它有效地完成),还是由编译器生成一系列指令(字节码系列)? 它是如此有用的东西,我只需要把它变成玩具语言Im建设 非常感谢你
(链接更受欢迎)
答案 0 :(得分:30)
Simon Peyton Jones的“函数式编程语言的实现”中给出了编译模式匹配的非常好的描述。它有点旧,但是一本非常好的书。除其他外,它还包含编译列表推导的描述。
Erlang编译器使用了本书中的这两种算法。
答案 1 :(得分:19)
您可以看到编译代码时会发生什么
-module(match).
-export([match/1]).
match(X) -> {a,Y} = X.
如果您想查看core
的外观> c(match, to_core).
或
$ erlc +to_core match.erl
结果是
module 'match' ['match'/1,
'module_info'/0,
'module_info'/1]
attributes []
'match'/1 =
%% Line 3
fun (_cor0) ->
case _cor0 of
<{'a',Y}> when 'true' ->
_cor0
( <_cor1> when 'true' ->
primop 'match_fail'
({'badmatch',_cor1})
-| ['compiler_generated'] )
end
'module_info'/0 =
fun () ->
call 'erlang':'get_module_info'
('match')
'module_info'/1 =
fun (_cor0) ->
call 'erlang':'get_module_info'
('match', _cor0)
如果你想看到光束的asm代码你可以做
> c(match, 'S').
或
$ erlc -S match.erl
和结果
{module, match}. %% version = 0
{exports, [{match,1},{module_info,0},{module_info,1}]}.
{attributes, []}.
{labels, 8}.
{function, match, 1, 2}.
{label,1}.
{func_info,{atom,match},{atom,match},1}.
{label,2}.
{test,is_tuple,{f,3},[{x,0}]}.
{test,test_arity,{f,3},[{x,0},2]}.
{get_tuple_element,{x,0},0,{x,1}}.
{test,is_eq_exact,{f,3},[{x,1},{atom,a}]}.
return.
{label,3}.
{badmatch,{x,0}}.
{function, module_info, 0, 5}.
{label,4}.
{func_info,{atom,match},{atom,module_info},0}.
{label,5}.
{move,{atom,match},{x,0}}.
{call_ext_only,1,{extfunc,erlang,get_module_info,1}}.
{function, module_info, 1, 7}.
{label,6}.
{func_info,{atom,match},{atom,module_info},1}.
{label,7}.
{move,{x,0},{x,1}}.
{move,{atom,match},{x,0}}.
{call_ext_only,2,{extfunc,erlang,get_module_info,2}}.
正如您所看到的那样{test,is_tuple,...
,{test,test_arity,...
,{get_tuple_element,...
和{test,is_eq_exact,...
指示如何在波束中执行此匹配,并将其直接转换为波束的字节码。
Erlang编译器是在Erlang本身实现的,您可以在compile模块的源代码中查看编译的每个阶段,并在依赖模块中查看详细信息。
答案 2 :(得分:13)
如果你想构建自己的模式匹配器,有一个paper by Scott and Ramsey和一个paper by Luc Maranget,它们都描述了如何将模式编译为有效的决策树(也就是嵌套的switch语句)。
答案 3 :(得分:2)
我能建议的最好的事情是编译一些测试函数并查看生成的代码。
erlc -S test.erl
生成test.S,这是相当可读的。
要回答这个问题,模式匹配是从更原始的操作中有效地建立起来的。这是匹配{X,[H | T]}的函数子句的代码的一部分。
{test,is_tuple,{f,1},[{x,0}]}.
{test,test_arity,{f,1},[{x,0},2]}.
{get_tuple_element,{x,0},0,{x,1}}.
{get_tuple_element,{x,0},1,{x,2}}.
{test,is_nonempty_list,{f,4},[{x,2}]}.