分离计算部分

在一些程序里,我们可能希望将计算部分完全隔离出来,以免影响其它程序。Erlang shell就是这样一个东西。第??章那个简单的shell是有缺陷的。在它里面运行的一个表达式可能通过这几种方式影响到进程:

  • 它可以发送进程标示符给其他进程(self/0),然后就可以与这个进程建立连接,给它发送消息。
  • 它可以注册或注销一个进程程序8.1用另外一种方法实现了一个shell:

程序8.1

  1. -module(c_shell).
  2. -export([start/0, eval/2]).
  3.  
  4. start() ->
  5. process_flag(trap_exit, true),
  6. go().
  7.  
  8. go() ->
  9. eval(io:parse_exprs('-> ')),
  10. go().
  11.  
  12. eval({form, Exprs}) ->
  13. Id = spawn_link(c_shell, eval, [self(), Exprs]),
  14. receive
  15. {value, Res, _} ->
  16. io:format("Result: ~w~n", [Res]),
  17. receive
  18. {'EXIT', Id, _ } ->
  19. true
  20. end;
  21. {'EXIT', Id, Reason} ->
  22. io:format("Error: ~w!~n", [Reason])
  23. end;
  24.  
  25. eval(_) ->
  26. io:format("Syntax Error!~n", []).
  27.  
  28. eval(Id, Exprs) ->
  29. Id ! eval:exprs(Exprs, []).

shell进程捕获EXIT信号。命令在一个与shell进程连接的单独的进程(spawn_link(c_shell,eval,[self(),Exprs]))中运行。尽管事实上我们把shell进程的进程ID给了c_shell:eval/2,但是因为对于作为实际执行者的eval:exprs/2函数,并没有给它任何参数,因此也就不会对造成影响。