Erlang点滴--try语句里的尾递归

像Erlang这种函数式编程语言,尾递归的使用对于减少栈开销是很重要的。尽管Erlang并不提倡防御式编程,但仍然提供了 try ... of ... catch ... after ... end 语句。这里有个需要注意的地方:try 语句模块里面的函数调用有可能无法形成尾递归。

下面是一个小实验:

 1 -module(test).
 2 -compile(export_all).
 3
 4 -define(LOOP_CNT, 10000000).
 5
 6 start_loop() ->
 7     timer:tc(fun loop/1, [?LOOP_CNT]).
 8 loop(N) when N =< 0 ->
 9     erlang:process_info(erlang:self(), stack_size);
10 loop(N) ->
11     loop(N-1).
12
13 start_try_loop() ->
14     timer:tc(fun try_loop/1, [?LOOP_CNT]).
15 try_loop(N) when N =< 0 ->
16     erlang:process_info(erlang:self(), stack_size);
17 try_loop(N) ->
18     try try_loop(N-1) catch _:_ -> void end.
19
20 start_of_loop() ->
21     timer:tc(fun of_loop/1, [?LOOP_CNT]).
22 of_loop(N) when N =< 0 ->
23     erlang:process_info(erlang:self(), stack_size);
24 of_loop(N) ->
25     try N=N of _ -> of_loop(N-1) catch _:_ -> void end.
26
27 start_catch_loop() ->
28     timer:tc(fun catch_loop/1, [?LOOP_CNT]).
29 catch_loop(N) when N =< 0 ->
30     erlang:process_info(erlang:self(), stack_size);
31 catch_loop(N) ->
32     try N=e of _ -> void catch _:_ -> catch_loop(N-1) end.

实验结果印证了一开始的观点,仔细想想理应是这样的。

Erlang点滴--try语句里的尾递归,布布扣,bubuko.com

时间: 2024-10-12 18:40:03

Erlang点滴--try语句里的尾递归的相关文章

PL/SQL的ROWTYPE在insert和update语句里的妙用

PL/SQL里的ROWTYPE类型具有非常大的用处和灵活性,现在发现ROWTYPE在insert和update语句里的妙用,可以节省很多代码,特别是在行copy和更新的时候.我在google的搜索结果里,看洋文看的头晕晕的时候找到的,惊喜啊!在oracle官方网站的手册里竟然没有这个,不知道咋回事. declare  v_dept dept%rowtype;begin    v_dept.deptno := 60;    v_dept.dname := 'sample';    v_dept.l

3.2.5.6 查找英语语句里所有形容词

3.2.5.6 查找英语语句里所有形容词 如果想查找在一段文字里所有出现匹配的字符,需要使用findall()函数,而不是使用search()函数.例如,如果有一个英语作家想把一段英语里所有形容词查找出来,他或她就会使用findall()来实现这个功能. 例子: text = "He was carefully disguised but captured quickly by police." print(text) print(re.findall(r"\w+ly&quo

Sql语句里的递归查询

Sql语句里的递归查询 SqlServer2005和Oracle 两个版本 以前使用Oracle,觉得它的递归查询很好用,就研究了一下SqlServer,发现它也支持在Sql里递归查询举例说明:SqlServer2005版本的Sql如下:比如一个表,有id和pId字段,id是主键,pid表示它的上级节点,表结构和数据:CREATE TABLE [aaa]( [id] [int] NULL, [pid] [int] NULL, [name] [nchar](10))GOINSERT INTO aa

mysql.select语句里怎样批量的在一个字段前面加指定字符

mysql.select语句里怎样批量的在一个字段前面加指定字符?也就是update语句怎样写才能实现? 假设现在需要更新的字段是name,对应的值是value,现在要将字符"B"批量的加到原来值之前,变成Bvalue,请问update语句怎么写? update tablename set name=concat("B",name); mysql.select语句里怎样批量的在一个字段前面加指定字符

C语言中while语句里使用scanf的技巧

今天友人和我讨论了一段代码,是HDU的OJ上一道题目的解,代码如下 #include<stdio.h> { int a,b; while(~scanf("%d%d",&a,&b)) { printf("%d\n",a+b); } return 0; } 起初,我以为代码中while语句里的按位取反运算符写错了,应该是逻辑非运算符. 这时我在Quora上找到了类似的问题,我对其中一篇答案做了修改和翻译: 查阅scanf函数的man手册,关于

Erlang点滴--杀死gen_server

前天同事碰到了一个问题:他为游戏写了一个模拟客户端的机器人程序,用的是gen_server行为.但是他启动这些机器人时并没有通过监控树,而是直接在Shell下启动了若干个.然后他就发现如果其中一个机器人进程挂掉的话,所有的机器人都会跟着挂掉. 当他把问题告诉我时我第一反应就是Shell挂掉了,因为所有的机器人都是在Shell下用start_link启动的,也就是说所有的机器人进程都和Shell进程建立了连接.因此如果其中一个机器人挂掉,它会向Shell发送EXIT消息导致Shell挂掉,Shel

NGINX实现IF语句里的AND,OR多重判断

原理 就是用SET变量进行. AND 就用变量叠加,OR就用0或1切换. nginx的配置中不支持if条件的逻辑与/逻辑或运算 ,并且不支持if的嵌套语法,我们可以用变量的方式来实现: 首先是伪代码(即不被nginx支持),写在这里只是为了方便理解: if ($remote_addr ~ "^(12.34|56.78)" && $http_user_agent ~* "spider") { return 403; } 这是等效的,并真实可用的配置 s

Erlang点滴--当广播卡住时

很多时候游戏服务器总避免不了要向玩家广播一些消息,我所遇到的问题是假如这个广播操作由一个进程来对待广播玩家逐个进行的话,很容易让该进程卡住(尤其是在网络状况不好或者玩家数量太多的情况下). 查了查大部分情况是卡在了fun prim_inet:send/3上,这其实是由于之前的广播直接调用了fun gen_tcp:send/2,而这其实是一个同步调用,一层一层剥代码就可以知道是怎么回事儿了. 首先这是fun gen_tcp:send/2的源码: 1 send(S, Packet) when is_

Sql语句里的递归查询 SqlServer2005和Oracle 两个版本

以前使用Oracle,觉得它的递归查询很好用,就研究了一下SqlServer,发现它也支持在Sql里递归查询举例说明:SqlServer2005版本的Sql如下:比如一个表,有id和pId字段,id是主键,pid表示它的上级节点,表结构和数据:CREATE TABLE [aaa]( [id] [int] NULL, [pid] [int] NULL, [name] [nchar](10))GOINSERT INTO aaa VALUES(1,0,'a')INSERT INTO aaa VALUE