![](/icons/12441dou.gif)
![](/icons/12441dou.gif)
![](/icons/12441de.gif)
![](/icons/12441dou2.gif)
![](/icons/12441yi.gif)
![](/icons/12441de.gif)
![](/icons/12441de.gif)
![](/icons/12441dou2.gif)
![](/icons/12441dou.gif)
![](/icons/12441dou.gif)
![](/icons/12441de.gif)
![](/icons/12441de.gif)
![](/icons/12441yi.gif)
![](/icons/12441dou2.gif)
![](/icons/12441yi.gif)
![](/icons/12441hanshu.gif)
![](/icons/12441de.gif)
![](/icons/12441dou2.gif)
![](/icons/12441de.gif)
![](/icons/12441dou.gif)
![](/icons/12441de.gif)
![](/icons/12441dou2.gif)
我们首先高屋建瓴地看
![](/icons/12441yi.gif)
![](/icons/12441de.gif)
![](/icons/12441dou.gif)
![](/icons/12441yi.gif)
![](/icons/12441de.gif)
![](/icons/12441dou2.gif)
$ # 首先定义业务规则
$ echo "buy 9000 shares of GOOG when price is less than 500" > biz_rules.txt
$ echo "sell 400 shares of MSFT when price is greater than 30" >> biz_rules.txt
$ echo "buy 7000 shares of AAPL when price is less than 160" >> biz_rules.txt
$ erl # 启动Erlang仿真器(类似于irb或者beanshell)
1> c(dsl). % compile and load, assumes dsl.erl is in the current directory
2> Pid = spawn(fun
-> dsl:broker
end). % start a broker in parallel
3> Functions = dsl:load_biz_rules(Pid, "biz_rules.txt").
4> MarketData = [{'GOOG', 498}, {'MSFT', 30}, {'AAPL', 158}].
5> dsl:apply_biz_rules(Functions, MarketData).
Order placed: buying 9000 shares of 'GOOG'
Order placed: buying 7000 shares of 'AAPL'
实现 前 3行echo命令创建biz_rules.txt文件![](/icons/12441dou.gif)
![](/icons/12441dou2.gif)
![](/icons/12441de.gif)
![](/icons/12441de.gif)
![](/icons/12441dou2.gif)
buy 9000 shares of GOOG when price is less than 500
sell 400 shares of MSFT when price is greater than 30
buy 7000 shares of AAPL when price is less than 160
我们![](/icons/12441de.gif)
![](/icons/12441yi.gif)
![](/icons/12441de.gif)
![](/icons/12441dou.gif)
![](/icons/12441yi.gif)
![](/icons/12441dou2.gif)
![](/icons/12441dou.gif)
![](/icons/12441yi.gif)
![](/icons/12441de.gif)
![](/icons/12441hanshu.gif)
![](/icons/12441dou2.gif)
1>c(dsl). % compiles and loads, assumes dsl.erl is in the current directory
产生![](/icons/12441yi.gif)
![](/icons/12441hanshu.gif)
![](/icons/12441dou2.gif)
broker
->
receive
{buy, Quantity, Ticker} ->
% 向外部系统下单
具体代码放在这里
%
Msg = "Order placed: buying ~p shares of ~p",
io:format(Msg, [Quantity, Ticker]),
broker
;
{sell, Quantity, Ticker} ->
% 向外部系统下单
具体代码放在这里
%
Msg = "Order placed: selling ~p shares of ~p",
io:format(Msg, [Quantity, Ticker]),
broker![](/icons/12441kh.gif)
end.
broker![](/icons/12441hanshu.gif)
![](/icons/12441diaoyong.gif)
![](/icons/12441dou2.gif)
![](/icons/12441de.gif)
![](/icons/12441de.gif)
![](/icons/12441dou2.gif)
![](/icons/12441yi.gif)
![](/icons/12441dou.gif)
![](/icons/12441de.gif)
![](/icons/12441dou2.gif)
请注意broker是尾递归
![](/icons/12441de.gif)
![](/icons/12441dou2.gif)
![](/icons/12441dou.gif)
![](/icons/12441yi.gif)
![](/icons/12441de.gif)
![](/icons/12441dou2.gif)
![](/icons/12441dou.gif)
![](/icons/12441yinwei.gif)
![](/icons/12441hanshu.gif)
![](/icons/12441de.gif)
![](/icons/12441dou2.gif)
![](/icons/12441de.gif)
![](/icons/12441dou.gif)
![](/icons/12441dou2.gif)
![](/icons/12441dou.gif)
![](/icons/12441dou2.gif)
给仿真器
![](/icons/12441de.gif)
![](/icons/12441yi.gif)
![](/icons/12441hanshu.gif)
![](/icons/12441de.gif)
![](/icons/12441dou.gif)
![](/icons/12441dou2.gif)
![](/icons/12441de.gif)
![](/icons/12441dou2.gif)
2> Pid = spawn(fun
-> dsl:broker
end). % call broker in parallel
在Erlang里![](/icons/12441dou.gif)
![](/icons/12441hanshu.gif)
![](/icons/12441dou.gif)
![](/icons/12441dou2.gif)
![](/icons/12441de.gif)
![](/icons/12441dou.gif)
![](/icons/12441yinwei.gif)
![](/icons/12441de.gif)
![](/icons/12441hanshu.gif)
![](/icons/12441dou2.gif)
![](/icons/12441de.gif)
![](/icons/12441hanshu.gif)
![](/icons/12441dou.gif)
![](/icons/12441yi.gif)
![](/icons/12441dou2.gif)
我们不打算深入讲解Erlang
![](/icons/12441de.gif)
![](/icons/12441dou2.gif)
![](/icons/12441yi.gif)
![](/icons/12441de.gif)
![](/icons/12441dou.gif)
![](/icons/12441dou2.gif)
![](/icons/12441de.gif)
![](/icons/12441hanshu.gif)
![](/icons/12441yi.gif)
![](/icons/12441dou.gif)
![](/icons/12441dou2.gif)
加载业务规则
![](/icons/12441de.gif)
![](/icons/12441yi.gif)
![](/icons/12441diaoyong.gif)
![](/icons/12441dou.gif)
![](/icons/12441de.gif)
![](/icons/12441yi.gif)
![](/icons/12441hanshu.gif)
![](/icons/12441dou2.gif)
3> Functions = dsl:load_biz_rules(Pid, "biz_rules.txt").
传给load_biz_rules![](/icons/12441de.gif)
![](/icons/12441de.gif)
![](/icons/12441de.gif)
![](/icons/12441de.gif)
![](/icons/12441yi.gif)
![](/icons/12441hanshu.gif)
![](/icons/12441dou2.gif)
![](/icons/12441hanshu.gif)
![](/icons/12441de.gif)
![](/icons/12441hanshu.gif)
![](/icons/12441dou.gif)
![](/icons/12441hanshu.gif)
![](/icons/12441de.gif)
![](/icons/12441dou2.gif)
![](/icons/12441yi.gif)
![](/icons/12441de.gif)
![](/icons/12441dou.gif)
![](/icons/12441yi.gif)
![](/icons/12441yi.gif)
![](/icons/12441dou.gif)
![](/icons/12441de.gif)
![](/icons/12441de.gif)
![](/icons/12441dou.gif)
![](/icons/12441dou2.gif)
load_biz_rules所返回
![](/icons/12441de.gif)
![](/icons/12441yi.gif)
![](/icons/12441hanshu.gif)
![](/icons/12441dou.gif)
![](/icons/12441de.gif)
![](/icons/12441yi.gif)
![](/icons/12441dou2.gif)
![](/icons/12441dou.gif)
![](/icons/12441yi.gif)
![](/icons/12441dou.gif)
![](/icons/12441hanshu.gif)
![](/icons/12441dou2.gif)
load_biz_rules(Pid, File) ->
{ok, Bin} = file:read_file(File),
Rules =
:tokens(erlang:binary_to_list(Bin), "n"),
[rule_to_function(Pid, Rule) || Rule <- Rules].
load_biz_rules![](/icons/12441hanshu.gif)
![](/icons/12441dou2.gif)
![](/icons/12441de.gif)
![](/icons/12441yi.gif)
![](/icons/12441zifu.gif)
![](/icons/12441dou.gif)
![](/icons/12441de.gif)
![](/icons/12441dou2.gif)
![](/icons/12441dou.gif)
![](/icons/12441hanshu.gif)
![](/icons/12441de.gif)
![](/icons/12441yi.gif)
![](/icons/12441hanshu.gif)
![](/icons/12441de.gif)
![](/icons/12441yi.gif)
![](/icons/12441dou.gif)
![](/icons/12441dou2.gif)
![](/icons/12441de.gif)
![](/icons/12441yi.gif)
![](/icons/12441yi.gif)
![](/icons/12441dou.gif)
![](/icons/12441yi.gif)
![](/icons/12441hanshu.gif)
![](/icons/12441dou2.gif)
熟悉列表推导
![](/icons/12441de.gif)
![](/icons/12441dou.gif)
![](/icons/12441dou2.gif)
![](/icons/12441de.gif)
![](/icons/12441yi.gif)
![](/icons/12441de.gif)
![](/icons/12441dou.gif)
![](/icons/12441de.gif)
![](/icons/12441dou2.gif)
![](/icons/12441hanshu.gif)
![](/icons/12441de.gif)
![](/icons/12441dou2.gif)
![](/icons/12441dou.gif)
![](/icons/12441yi.gif)
![](/icons/12441de.gif)
![](/icons/12441de.gif)
![](/icons/12441de.gif)
![](/icons/12441yi.gif)
![](/icons/12441de.gif)
![](/icons/12441hanshu.gif)
![](/icons/12441yi.gif)
![](/icons/12441dou2.gif)
rule_to_function(Pid, Rule) ->
{ok, Scanned, _} = erl_scan:
(Rule),
[{_,_,Action},{_,_,Quantity},_,_|Tail] = Scanned,
[{_,_,Ticker},_,_,_,{_,_,Operator},_,{_,_,Limit}] = Tail,
to_function(Pid, Action, Quantity, Ticker, Operator, Limit).
第![](/icons/12441yi.gif)
![](/icons/12441de.gif)
![](/icons/12441zifu.gif)
![](/icons/12441yi.gif)
![](/icons/12441dou2.gif)
![](/icons/12441de.gif)
![](/icons/12441dou2.gif)
![](/icons/12441de.gif)
![](/icons/12441dou2.gif)
![](/icons/12441de.gif)
![](/icons/12441de.gif)
![](/icons/12441hanshu.gif)
![](/icons/12441dou2.gif)
![](/icons/12441yi.gif)
![](/icons/12441de.gif)
![](/icons/12441hanshu.gif)
![](/icons/12441dou2.gif)
我们将讨论to_function
![](/icons/12441de.gif)
![](/icons/12441dou.gif)
![](/icons/12441yi.gif)
![](/icons/12441de.gif)
![](/icons/12441dou2.gif)
to_function(Pid, Action, Quantity, Ticker, Operator, Limit) ->
fun(Ticker_, Price) ->
![](/icons/12441if.gif)
Ticker =:= Ticker_ andalso
( ( Price < Limit andalso Operator =:= less ) or![](/icons/12441else.gif)
( Price > Limit andalso Operator =:= greater ) ) ->
Pid ! {Action, Quantity, Ticker}; % place an order
true ->
erlang:display("no rule applied")
end
end.
这个to_function实现做了![](/icons/12441yi.gif)
![](/icons/12441yi.gif)
![](/icons/12441hanshu.gif)
![](/icons/12441dou2.gif)
![](/icons/12441hanshu.gif)
![](/icons/12441de.gif)
![](/icons/12441dou2.gif)
![](/icons/12441hanshu.gif)
![](/icons/12441de.gif)
![](/icons/12441dou.gif)
![](/icons/12441de.gif)
![](/icons/12441dou2.gif)
![](/icons/12441dou.gif)
![](/icons/12441yi.gif)
![](/icons/12441dou.gif)
![](/icons/12441dou2.gif)
加载业务规则
![](/icons/12441de.gif)
![](/icons/12441de.gif)
![](/icons/12441yi.gif)
![](/icons/12441dou2.gif)
![](/icons/12441yi.gif)
![](/icons/12441de.gif)
![](/icons/12441dou.gif)
![](/icons/12441yi.gif)
![](/icons/12441hanshu.gif)
![](/icons/12441dou.gif)
![](/icons/12441dou2.gif)
to_function(Pid, Action, Quantity, Ticker, Operator, Limit) ->
Abstract = rule_to_abstract(Action, Quantity, Ticker, Operator, Limit),
fun(Ticker_, Price) ->
TickerBinding = erl_eval:add_binding('Ticker', Ticker_, erl_eval:
_bindings
),
PriceBindings = erl_eval:add_binding('Price', Price, TickerBinding),
Bindings = erl_eval:add_binding('Pid', Pid, PriceBindings),
erl_eval:exprs(Abstract, Bindings)
end.
![](/icons/12441hanshu.gif)
![](/icons/12441de.gif)
![](/icons/12441yi.gif)
![](/icons/12441hanshu.gif)
![](/icons/12441dou2.gif)
![](/icons/12441dou.gif)
![](/icons/12441de.gif)
![](/icons/12441dou2.gif)
rule_to_abstract(Action, Quantity, Ticker, Operator, Limit) ->
Comparison =
Operator =:= greater -> '>'; true -> '<' end,
[{'
',1,
[{clause,1,
,
[[{op,1,
'andalso',
{op,1,'=:=',{atom,1,Ticker},{var,1,'Ticker'}},
{op,1,Comparison,{var,1,'Price'},{
eger,1,Limit}}}]],
[{op,1,
'!',
{var,1,'Pid'},
{tuple,1,[{atom,1,Action},
{
eger,1,Quantity},
{atom,1,Ticker}]}}]},
{clause,1,
,
[[{atom,1,true}]],
[{call,1,
{remote,1,{atom,1,erlang},{atom,1,display}},
[{
,1,"no rule applied"}]}]}]}].
rule_to_abstract![](/icons/12441hanshu.gif)
![](/icons/12441yi.gif)
![](/icons/12441de.gif)
![](/icons/12441dou2.gif)
![](/icons/12441yi.gif)
![](/icons/12441de.gif)
![](/icons/12441yi.gif)
![](/icons/12441if.gif)
![](/icons/12441dou2.gif)
![](/icons/12441yi.gif)
![](/icons/12441dou.gif)
![](/icons/12441de.gif)
![](/icons/12441de.gif)
![](/icons/12441dou.gif)
![](/icons/12441yi.gif)
![](/icons/12441de.gif)
![](/icons/12441dou2.gif)
![](/icons/12441dou.gif)
![](/icons/12441de.gif)
![](/icons/12441de.gif)
![](/icons/12441if.gif)
Ticker =:= ‘GOOG’ andalso Price < 500 ->
Pid ! {sell, 9000, ‘GOOG’}; % place order with broker
true ->
erlang:display("no rule applied")
end
这个版本![](/icons/12441de.gif)
![](/icons/12441de.gif)
![](/icons/12441dou.gif)
![](/icons/12441yi.gif)
![](/icons/12441hanshu.gif)
![](/icons/12441yi.gif)
![](/icons/12441de.gif)
![](/icons/12441yi.gif)
![](/icons/12441dou2.gif)
![](/icons/12441hanshu.gif)
![](/icons/12441dou.gif)
![](/icons/12441dou.gif)
![](/icons/12441hanshu.gif)
![](/icons/12441de.gif)
![](/icons/12441dou2.gif)
![](/icons/12441de.gif)
![](/icons/12441hanshu.gif)
![](/icons/12441de.gif)
![](/icons/12441dou2.gif)
应用业务规则 现在我们加载了业务规则
![](/icons/12441dou.gif)
![](/icons/12441hanshu.gif)
![](/icons/12441dou.gif)
![](/icons/12441dou2.gif)
![](/icons/12441yi.gif)
![](/icons/12441dou2.gif)
![](/icons/12441yi.gif)
![](/icons/12441dou2.gif)
4> MarketData = [{'GOOG', 498}, {'MSFT', 30}, {'AAPL', 158}].
5> dsl:apply_biz_rules(Functions, MarketData).
把![](/icons/12441hanshu.gif)
![](/icons/12441de.gif)
![](/icons/12441dou.gif)
![](/icons/12441hanshu.gif)
![](/icons/12441dou2.gif)
apply_biz_rules(Functions, MarketData) ->
lists:map(fun({Ticker,Price}) ->
lists:map(fun(Function) ->
Function(Ticker, Price)
end, Functions)
end, MarketData).
幸亏我们只有 3条业务规则![](/icons/12441dou.gif)
![](/icons/12441yinwei.gif)
![](/icons/12441de.gif)
![](/icons/12441de.gif)
![](/icons/12441dou2.gif)
![](/icons/12441de.gif)
![](/icons/12441dou.gif)
![](/icons/12441de.gif)
![](/icons/12441dou2.gif)
![](/icons/12441hanshu.gif)
![](/icons/12441yi.gif)
![](/icons/12441hanshu.gif)
![](/icons/12441de.gif)
![](/icons/12441yi.gif)
![](/icons/12441dou2.gif)
![](/icons/12441hanshu.gif)
![](/icons/12441hanshu.gif)
![](/icons/12441yi.gif)
![](/icons/12441hanshu.gif)
![](/icons/12441dou2.gif)
![](/icons/12441hanshu.gif)
![](/icons/12441hanshu.gif)
执行apply_biz_rules
![](/icons/12441dou.gif)
![](/icons/12441de.gif)
![](/icons/12441dou2.gif)
5> dsl:apply_biz_rules(Functions, MarketData).
Order placed: buying 9000 shares of 'GOOG'
Order placed: buying 7000 shares of 'AAPL'
执行结果中没有买入或卖出Microsoft![](/icons/12441de.gif)
![](/icons/12441dou2.gif)
![](/icons/12441yi.gif)
![](/icons/12441dou.gif)
![](/icons/12441yi.gif)
![](/icons/12441chengxu.gif)
![](/icons/12441de.gif)
![](/icons/12441de.gif)
![](/icons/12441dou2.gif)
buy 9000 shares of GOOG when price is less than 500
sell 400 shares of MSFT when price is greater than 30
buy 7000 shares of AAPL when price is less than 160
4> MarketData = [{'GOOG', 498}, {'MSFT', 30}, {'AAPL', 158}].
如果Google![](/icons/12441de.gif)
![](/icons/12441dou.gif)
![](/icons/12441de.gif)
![](/icons/12441dou.gif)
![](/icons/12441de.gif)
![](/icons/12441dou2.gif)
sell 400 shares of MSFT when price is greater than 27
6> UpdatedFunctions = dsl:load_biz_rules(Pid, "
_biz_rules.txt").
7> UpdatedMarketData = [{'GOOG', 505}, {'MSFT', 30}, {'AAPL', 158}].
8> dsl:apply_biz_rules(UpdatedFunctions, UpdatedMarketData).
Order placed: selling 400 shares of 'MSFT'
Order placed: buying 7000 shares of 'AAPL'
结论 再重申![](/icons/12441yi.gif)
![](/icons/12441de.gif)
![](/icons/12441de.gif)
![](/icons/12441dou2.gif)
![](/icons/12441hanshu.gif)
![](/icons/12441dou2.gif)
![](/icons/12441de.gif)
![](/icons/12441dou2.gif)
![](/icons/12441de.gif)
![](/icons/12441smhl.gif)
![](/icons/12441string.gif)
![](/icons/12441smhr.gif)
![](/icons/12441yi.gif)
![](/icons/12441de.gif)
![](/icons/12441dou2.gif)
![](/icons/12441yi.gif)
![](/icons/12441de.gif)
![](/icons/12441dou.gif)
![](/icons/12441yi.gif)
![](/icons/12441de.gif)
![](/icons/12441dou2.gif)
![](/icons/12441de.gif)
![](/icons/12441dou2.gif)
有关作者 Dennis Byrne就职于ThoughtWorks
![](/icons/12441dou.gif)
![](/icons/12441yi.gif)
![](/icons/12441de.gif)
![](/icons/12441dou.gif)
![](/icons/12441de.gif)
![](/icons/12441dou2.gif)
![](/icons/12441de.gif)
![](/icons/12441dou.gif)
![](/icons/12441int.gif)
![](/icons/12441de.gif)
![](/icons/12441dou2.gif)
最新评论