[1] Erlang 语言设计的目标是并发,支持并发的核心机制是进程 "Making reliable distributed systems in the presence of sodware errors"  [PDF

 

[2] 并发是一种不按照顺序执行的能力,并行是从处理执行的角度"是否可以同时做";还有一种角度:并发是逻辑上的同时发生(simultaneous),并行是物理上的同时发生.

 

[3]其实无论是面向过程还是面向对象,各种编程范式都是对现实世界中的一种抽象 ,只不过关注的点不同

 

[4]Shared  memory  could  reasonably  be  called  the  GOTO  of  our  time:  it’s  the  current mainstream  technique  for  process  communication;  it  has  been  so  for  a  long,  long time;  and  just  like  programming  with  GOTO,  there  are  numerous  ways  to  shoot  yourself  in  the  foot.

 

[5]  In  Erlang,  the  message  passing  primitives are asynchronous, because it’s easy to implement the synchronous form when necessary by      making the receiver always send an explicit reply that the sender can wait for. 

 

[6] Copying data can be expensive for large structures and can cause higher memory  usage  if  the  sender  also  needs  to  keep  their  copy  of  the  data.  In  practice,  this means you must be aware of and manage the size and complexity of messages you’re sending.  But  in  normal,  idiomatic  Erlang  programs,  the  majority  of  messages  are small, and the overhead of copying is usually negligible.
 
[7]A typical thread in a modern operating system reserves some megabytes of address space  for  its  stack  (which  means  a  32-bit  machine  can  never  have  more  than  a  few thousand simultaneous threads), and it still crashes if it uses more stack space than expected. Erlang processes, on the other hand, start with only a couple of hundred bytes of stack space each, and they grow or shrink automatically as required.
 
[8]OTP framework provides just about everything you need: both a methodology for structuring applications using supervision, and stable, battle-hardened libraries to build them on.
 
[9] At  the  lowest  levels  of  the  system, Erlang does all I/O in an event-based way, which lets a program handle each chunk of data as it enters or leaves the system in a nonblocking manner. This reduces the need to set up and tear down connections, and it removes the need for OS-based locking and context switching.
 
[10] 对于代码中的常量在HIPE的时候会编译优化放在池中,比如下面的代码就不会反复创建常量字符串

 

para(Text) ->

   ["<p class=\"normal\">", Text, "</p>"]. 

http://prog21.dadgum.com/10.html

 

[11]  hipe_bifs:bitarray 提供了类似Redis命令中setbit getbit的作用 @yufeng的介绍

Eshell V5.9  (abort with ^G)

1> hipe_bifs:bitarray(10,false).

<<0,0>>

2> hipe_bifs:bitarray_update(v(1), 3, true).

<<8,0>>

3> hipe_bifs:bitarray_update(v(2), 7, true).

<<136,0>>

4> hipe_bifs:bitarray_update(v(3), 1, true).

<<138,0>>

5> hipe_bifs:bitarray_sub(v(4), 1).

true

6> hipe_bifs:bitarray_sub(v(4), 2).

false

7> hipe_bifs:bitarray_sub(v(4), 3).

true

8> hipe_bifs:bitarray_sub(v(4), 4).

false

9> hipe_bifs:bitarray_sub(v(4), 7).

true

10> 

 

 

[12]  The external term format is mainly used in the distribution mechanism of Erlang.

http://www.erlang.org/doc/apps/erts/erl_ext_dist.html 看下面的测试代码

 

Eshell V5.9  (abort with ^G)
(node_b@192.168.10.160)1> net_adm:ping('node_a@192.168.10.160').
pong
(node_b@192.168.10.160)2> {a_shell,'node_a@192.168.10.160'}!hello_world.
hello_world
(node_b@192.168.10.160)3> {a_shell,'node_a@192.168.10.160'}!self().     
<0.38.0>
(node_b@192.168.10.160)4> 

 

Eshell V5.9  (abort with ^G)
(node_a@192.168.10.160)1> register(a_shell,self()).     
true
(node_a@192.168.10.160)2> flush().
Shell got hello_world
ok
(node_a@192.168.10.160)3> flush().
Shell got <5911.38.0>
ok
(node_a@192.168.10.160)4> node(pid(5911,38,0)).
'node_b@192.168.10.160'
(node_a@192.168.10.160)5> 

 

 

 

[13] 为什么shell进程重启了,原来的变量还在

   可以看一下 erl5.9.1\lib\stdlib-1.18.1\src\shell.erl的代码 ,shell进程遇到异常之后的处理逻辑 包含变量绑定的重建shell_rep(Ev, Bs0, RT, Ds0) 方法

 

Eshell V5.9.1  (abort with ^G)
1> self().
<0.30.0>
2> B=23.
23
3> 1/0.
** exception error: bad argument in an arithmetic expression
     in operator  '/'/2
        called as 1 / 0
4> self().
<0.34.0>
5> B.
23
6> b().
B = 23
ok

 

代码片段:

 

View Code
shell_rep(Ev, Bs0, RT, Ds0) ->
    receive
     {shell_rep,Ev,{value,V,Bs,Ds}} ->
         {V,Ev,Bs,Ds};
        {shell_rep,Ev,{command_error,{Line,M,Error}}} ->
            fwrite_severity(benign, <<"~w: ~s">>,
                            [Line, M:format_error(Error)]),
            {{'EXIT',Error},Ev,Bs0,Ds0};
     {shell_req,Ev,get_cmd} ->
         Ev ! {shell_rep,self(),get()},
         shell_rep(Ev, Bs0, RT, Ds0);
     {shell_req,Ev,exit} ->
         Ev ! {shell_rep,self(),exit},
         exit(normal);
     {shell_req,Ev,{update_dict,Ds}} ->     % Update dictionary
         Ev ! {shell_rep,self(),ok},
         shell_rep(Ev, Bs0, RT, Ds);
        {ev_exit,{Ev,Class,Reason0}} ->         % It has exited unnaturally
            receive {'EXIT',Ev,normal} -> ok end,
         report_exception(Class, Reason0, RT),
            Reason = nocatch(Class, Reason0),
         {{'EXIT',Reason},start_eval(Bs0, RT, Ds0), Bs0, Ds0};
        {ev_caught,{Ev,Class,Reason0}} ->       % catch_exception is in effect
         report_exception(Class, benign, Reason0, RT),
            Reason = nocatch(Class, Reason0),
            {{'EXIT',Reason},Ev,Bs0,Ds0};
     {'EXIT',_Id,interrupt} ->          % Someone interrupted us
         exit(Ev, kill),
         shell_rep(Ev, Bs0, RT, Ds0);
        {'EXIT',Ev,{Reason,Stacktrace}} ->
            report_exception(exit, {Reason,Stacktrace}, RT),
         {{'EXIT',Reason},start_eval(Bs0, RT, Ds0), Bs0, Ds0};
        {'EXIT',Ev,Reason} ->
            report_exception(exit, {Reason,[]}, RT),
         {{'EXIT',Reason},start_eval(Bs0, RT, Ds0), Bs0, Ds0};
     {'EXIT',_Id,R} ->
         exit(Ev, R),
         exit(R);
     _Other ->                    % Ignore everything else
         shell_rep(Ev, Bs0, RT, Ds0)
    end.

 

[14] %模块已经加载而且具有指定的方法导出, 注意最后一个参数是Arity 代表几目运算

erlang:function_exported(Module, Function, Arity) -> bool()
Types:
Module = Function = atom()
Arity = int()
Returns true if the module Module is loaded and contains an exported function Function/Arity; otherwise
false.
Returns false for any BIF (functions implemented in C rather than in Erlang).

15.

IP地址转换 
1> inet_parse:address("127.0.0.1").
{ok,{127,0,0,1}}
2> inet_parse:address("::1").
{ok,{0,0,0,0,0,0,0,1}}
3> inet_parse:address("300.400.500.600").
{error,einval}
And here is Erlang tuple to string conversion:

1> inet_parse:ntoa({127,0,0,1}).
"127.0.0.1"
2> inet_parse:ntoa({0,0,0,0,0,0,0,1}).
"::1"