??xml version="1.0" encoding="utf-8" standalone="yes"?>亚洲人av高清无码,亚洲动漫精品无码av天堂,亚洲欧洲日产国码久在线观看http://m.tkk7.com/killme2008/category/20770.html天行健,君子以自Z?/description>zh-cnTue, 13 Apr 2010 11:17:26 GMTTue, 13 Apr 2010 11:17:26 GMT60Ruby Fiber指南Q五Q: 实现ActorQ兼谈Erlang的process调度http://m.tkk7.com/killme2008/archive/2010/04/13/318182.htmldennisdennisTue, 13 Apr 2010 10:31:00 GMThttp://m.tkk7.com/killme2008/archive/2010/04/13/318182.htmlhttp://m.tkk7.com/killme2008/comments/318182.htmlhttp://m.tkk7.com/killme2008/archive/2010/04/13/318182.html#Feedback0http://m.tkk7.com/killme2008/comments/commentRss/318182.htmlhttp://m.tkk7.com/killme2008/services/trackbacks/318182.html     Ruby Fiber指南Q一Q基
    Ruby Fiber指南Q二Q参C?/a>
   
Ruby Fiber指南Q三Q过滤器
    Ruby Fiber指南Q四QP代器
    Ruby Actor指南Q五Q实现Actor

    写这个指南的时候,计划是第五章写一个Fiber的应用例子,但是一时没有想到比较好的例子,模仿《Programming in Lua》中的多d下蝲的例子也不合适,因ؓRuby中的异步HttpClient跟luaq是很不一LQ体C了Fiber的优炏V因此,q第五节一直拖着没写?br />     恰y最q在组中做了一ơErlang的分享,有h问到Erlang调度器的实现问题Q这块我没注意过Q那时候就Ҏ我对coroutine实现actor的想法做了下解释Q后来思考了下那个解释是错误的,Erlang的调度器是抢占式的,而通过coroutine实现的actor调度却是非抢占的Q两者还是截然不同的。我在?a href="http://m.tkk7.com/killme2008/archive/2010/03/23/316273.html">Actor、Coroutine和Continuation的概忉|?/a>》中提到coroutine可以实现actor风格Qactor跟coroutineq没有必然的联系Q这文章的目的在于证明这一点,使用Ruby Fiber实现一个简单的actor风格的库Q整个代码不?00行。后面还会谈到这个实现的~点Q以及我对Erlang调度器实现的理解?br />
    首先是monkey patchQ给Thread和Fibercd上两个方法,分别用于获取当前U程的调度器和Fiber对应的actor:
class Thread
  
#得到当前U程的调度器
  def __scheduler__
    @internal_scheduler
||=FiberActor::Scheduler.new
  end
end

class Fiber
  
#得到当前Fiber的actor
  def __actor__
    @internal_actor
  end
end

     q里实现的actor仍然是Thread内的Q一个Thread只跑一个调度器Q每个actor兌一个Fiber?br />      让我们来x调度器该怎么实现,调度器顾名思义是协调actor的运行,每次挑选适当的actorq执行,可以惌调度器内部应该维护一个等待调度的actor队列QScheduler每次从队列里取出一个actorq执行,执行完之后取下一个actor执行Q不断@环持l这个过E;在没有actor可以调度的时候,调度器应该让出执行权。因此调度器本n也是一个FiberQ它内部有个queueQ用于维护等待调度的actorQ?br />
module FiberActor
  
class Scheduler
    
def initialize
      @queue
=[]
      @running
=false
    end

    
def run
      
return if @running
      @running
=true
      
while true
        
#取出队列中的actorq执?/span>
        while actor=@queue.shift
          begin
            actor.fiber.resume
          rescue 
=> ex
            puts 
"actor resume error,#{ex}"
          end
        end
        
#没有dQ让出执行权
        Fiber.yield
      end
    end

    
def reschedule
      
if @running
        
#已经启动Q只是被挂vQ那么再ơ执?/span>
        @fiber.resume
      
else
        
#当前actor加入队列
        self << Actor.current
      end
    end

    
def running?
      @running
    end

    
def <<(actor)
      
#actor加入{待队列
      @queue << actor unless @queue.last == actor
      
#启动调度?/span>
      unless @running
         @queue 
<< Actor.current
         @fiber
=Fiber.new { run }
         @fiber.resume
      end
    end
  end
end

    runҎ是核心的调度ҎQ注释说明了主要的工作流E。因度器可能让出执行权,因此提供了rescheduleҎ重新resume启动调度器?lt;<Ҏ用于等待被调度的actor加入{待队列Q如果调度器没有启动Q那么就启动调度Fiber?br />
    有了调度器,Actor的实C很简单,Actor跟Fiber是一对一的关p,Actor内部l护一个mailboxQ用来存储接收到的消息。最重要的是receive原语的实玎ͼ我们q里很简单,不搞模式匚wQ只是接收消息。receive的工作流E大概是q样Q判断mailbox中有没有消息Q有消息的话Q取出消息ƈ调用block处理Q没有消息的话就yield让出执行权?br />
module FiberActor  
  
class Actor
    attr_accessor :fiber
    
#定义cL?/span>
    class << self
      
def scheduler
        Thread.current.
__scheduler__
      end

      
def current
        Fiber.current.
__actor__
      end

      
#启动一个actor
      def spawn(*args,&block)
        fiber
=Fiber.new do
           block.call(args)
        end
        actor
=new(fiber)
        fiber.instance_variable_set :@internal_actor,actor
        scheduler 
<< actor
        actor
      end

      
def receive(&block)
        current.receive(
&block)
      end
    end

    
def initialize(fiber)
       @mailbox
=[]
       @fiber
=fiber
    end

    
#lactor发送消?/span>
    def << (msg)
      @mailbox 
<< msg
      
#加入调度队列
      Actor.scheduler << self
    end

    
def receive(&block)
      
#没有消息的时候,让出执行?/span>
      Fiber.yield while @mailbox.empty?
      msg
=@mailbox.shift
      block.call(msg)
    end

    
def alive?
      @fiber.alive?
    end
  end

end

    Actor.spawn用于启动一个actorQ内部其实是创徏了一个fiberq包装成actorl用P每个actor一被创建就加入调度器的{待队列?lt;<Ҏ用于向actor传递消息,传递消息后Q该actor也将加入{待队列Q等待被调度?br />
    我们的简化版actor库已l写完了Q可以尝试写几个例子Q最单的hello world:
include FiberActor

Actor.spawn { puts 
"hello world!"}
     输出Q?br />
hello world!

    没有问题Q那么试试传递消息:
actor=Actor.spawn{
   Actor.receive{ 
|msg|  puts "receive #{msg}"}
}
actor 
<< :test_message
    输出Q?br />
receive test_message
    
    也成了,那么试试两个actor互相传递消息,乒乓一下下Q?br />
pong=Actor.spawn do
      Actor.receive do 
|ping|
        
#收到pingQ返回pong
        ping << :pong
      end
    end
ping
=Actor.spawn do
      
#ping一下,ping作ؓ消息传?/span>
      pong << Actor.current
      Actor.receive do 
|msg|
        
#接收到pong
        puts "ping #{msg}"
      end
    end
#resume调度?/span>
Actor.scheduler.reschedule

     输出Q?br />
ping pong
    
     都没有问题,q个񔽎单actor基本完成了。可以看刎ͼ利用coroutine来实现actor是完全可行的Q事实上我这里描q的实现基本上是revactorq个库的实现原理?a >revactor是一个ruby的actor库,它的实现是ZFiberQƈ且支持消息的模式匚w和thread之间的actor调度Q有兴趣地可以去玩下。更q一步,其实采用轻量U协E来模拟actor风格早就不是新鲜LQ比如在cn-erlounge的第四次会议?/a>有两个topic是关于这个,一个是51.com利用Zucontext的实现的cerlangq程模型Q一个是怸伟的CERL。可以想见,他们的基本原理跟本文所描述不会有太大差别,那么面对的问题也是一栗?br />
     采用coroutine实现actor的主要缺点如下:
1、因为是非抢占式Q这p求actor不能有阻塞操作,Md操作都需要异步化。IO可以使用异步IOQ没有os原生支持的就需要利用线E池Q基本上是一个重复造轮子的q程?br /> 2、异常的隔离Q某个actor的异怸能媄响到调度器的q{Q简单的try...catch是不够的?br /> 3、多核的利用Q调度器只能跑在一个线E上Q无法充分利用多怼ѝ?br /> 4、效率因素,在actor数量剧增的情况下Q简单的FIFO的调度策略效率是个瓶颈,管coroutine的切换已l非帔R效?br />
    当然Q上面提到的q些问题q无法解决Q例如可以用多U程多个调度器,cMerlang smp那样来解军_个调度器的问题。但是如调度效率q样的问题是很难解决的。相反,erlang的actor实现׃是通过coroutineQ而是自己实现一套类似os的调度程序?br />     首先明确一点,Erlang的process的调度是抢占式的Q而非couroutine的协作式的。其ơ,Erlang早期版本是只有一个调度器Q运行在一个线E上Q随着erts的发展,现在erlang的调度器已经支持smpQ每个cpu兌一个调度器Qƈ且可以明指定哪个调度器l定到哪个cpu上。第三,Erlang的调度也是采用优先队?旉片轮询的方式Q每个调度器兌一?span id=":2v1">ErtsRunQueueQ?/span>ErtsRunQueue内部又分Z?/span>ErtsRunPrioQueue队列Q分别对应high,max和normal,low的优先Q其中normal和lowq一个队列;在Erlang中时间片是以reduction为单位,你可以将reduction理解成一ơ函数调用,每个被调度的process能执行的reductionơ数是有限的。调度器每次都是从max队列开始寻扄待调度的processq执行,当前调度的队列如果ؓI或者执行的reductions过限制Q那么就降低优先U,调度下一个队列?br />
   从上面的描述可以看出QErlang优秀的地方不仅在于actor风格的轻量processQ另一个强悍的地方是它的cos的调度器Q再加上OTP库的完美支持Q这不是一般方案能山寨的?br />     
    
  


dennis 2010-04-13 18:31 发表评论
]]>
Erlang介的PPTQ达人勿入)http://m.tkk7.com/killme2008/archive/2010/04/12/318031.htmldennisdennisMon, 12 Apr 2010 02:45:00 GMThttp://m.tkk7.com/killme2008/archive/2010/04/12/318031.htmlhttp://m.tkk7.com/killme2008/comments/318031.htmlhttp://m.tkk7.com/killme2008/archive/2010/04/12/318031.html#Feedback0http://m.tkk7.com/killme2008/comments/commentRss/318031.htmlhttp://m.tkk7.com/killme2008/services/trackbacks/318031.html


dennis 2010-04-12 10:45 发表评论
]]>
Rabbitmq的网l层析http://m.tkk7.com/killme2008/archive/2009/11/29/304079.htmldennisdennisSun, 29 Nov 2009 04:00:00 GMThttp://m.tkk7.com/killme2008/archive/2009/11/29/304079.htmlhttp://m.tkk7.com/killme2008/comments/304079.htmlhttp://m.tkk7.com/killme2008/archive/2009/11/29/304079.html#Feedback5http://m.tkk7.com/killme2008/comments/commentRss/304079.htmlhttp://m.tkk7.com/killme2008/services/trackbacks/304079.html     Rabbitmq是一个MQpȝQ也是消息中间Ӟ它实CAMQP 0.8规范Q简单来说就是一个TCP的广播服务器。AMQP协议Q你可以cLJMSQ不qJMS仅仅是java领域内的API规范Q而AMQP比JMS更进一步,它有自己的wire-level protocolQ有一套可~程的协议,中立于语a。简单介l了Rabbitmq之后Q进入正题?br />     Rabbitmq充分利用了Erlang的分布式、高可靠性、ƈ发等Ҏ,首先看它的一个结构图Q?br />


q张囑ֱCRabbitmq的主要组件和lg之间的关p,具体到监控树的结构,我画了一张图Q?br />






    层是rabbit_sup supervisorQ它臛_有两个子q程Q一个是rabbit_tcp_client_supQ用来监控每个connection的处理进E? rabbit_reader的supervisor;rabbit_tcp_listener_sup是监控tcp_listener? tcp_acceptor_sup的supervisorQtcp_listener里启动tcp服务器,监听端口Qƈ且通过tcp_acceptor_sup启动N个tcp_accetporQtcp_acceptor发vaccepthQ等待客Lq接;tcp_acceptor_sup负责监控q些acceptor。这张图已经能给你一个大体的印象?/strong>
   
    讲完大概Q进入细节,说说几个我觉的值的注意的地方:
1?strong>tcp_accepto.erl,r对于accept采用的是异步方式
Q利?strong>prim_inet:async_accept/2
? 法,此模块没有被文档化,是otp库内部?通常来说没必要用这一模块Qgen_tcp:accept/1已经_Q不qrabbitmq是广播程 序,因此采用了异步方式。用async_acceptQ需要打patchQ以使得socket好像我们从gen_tcp:accept/1得到的一P

handle_info({inet_async, LSock, Ref, {ok, Sock}},
            State = #state{callback={M,F,A}, sock=LSock, ref=Ref}) ->
    %%q里做了patch
    %% patch up the socket so it looks like one we got from
    %% gen_tcp:accept/1
    {ok, Mod} = inet_db:lookup_socket(LSock),
    inet_db:register_socket(Sock, Mod),

    try
        %% report
        {Address, Port}         = inet_op(fun () -> inet:sockname(LSock) end),
        {PeerAddress, PeerPort} = inet_op(fun () -> inet:peername(Sock) end),
        error_logger:info_msg("accepted TCP connection on ~s:~p from ~s:~p~n",
                              [inet_parse:ntoa(Address), Port,
                               inet_parse:ntoa(PeerAddress), PeerPort]),
        %% 调用回调模块Q将Sock作ؓ附加参数
        apply(M, F, A ++ [Sock])
    catch {inet_error, Reason} ->
            gen_tcp:close(Sock),
            error_logger:error_msg("unable to accept TCP connection: ~p~n",
                                   [Reason])
    end,

    %% l箋发v异步调用
    case prim_inet:async_accept(LSock, -1) of
        {ok, NRef} -> {noreply, State#state{ref=NRef}};
        Error -> {stop, {cannot_accept, Error}, none}
    end;
%%处理错误情况
handle_info({inet_async, LSock, Ref, {error, closed}},
            State=#state{sock=LSock, ref=Ref}) ->
    %% It would be wrong to attempt to restart the acceptor when we
    %% know this will fail.
    {stop, normal, State};

2?strong>rabbitmq内部是用了多个q发acceptorQ这在高q发下、大量连接情况下有效率优势,cMjava现在的nio框架采用多个reactorcMQ查看tcp_listener.erl:

init({IPAddress, Port, SocketOpts,
      ConcurrentAcceptorCount, AcceptorSup,
      {M,F,A} = OnStartup, OnShutdown, Label}) ->
    process_flag(trap_exit, true),
    case gen_tcp:listen(Port, SocketOpts ++ [{ip, IPAddress},
                                             {active, false}]) of
        {ok, LSock} ->
             %%创徏ConcurrentAcceptorCount个ƈ发acceptor
            lists:foreach(fun (_) ->
                                  {ok, _APid} = supervisor:start_child(
                                                  AcceptorSup, [LSock])
                          end,
                          lists:duplicate(ConcurrentAcceptorCount, dummy)),

            {ok, {LIPAddress, LPort}} = inet:sockname(LSock),
            error_logger:info_msg("started ~s on ~s:~p~n",
                                  [Label, inet_parse:ntoa(LIPAddress), LPort]),
            %%调用初始化回调函?br />             apply(M, F, A ++ [IPAddress, Port]),
            {ok, #state{sock = LSock,
                        on_startup = OnStartup, on_shutdown = OnShutdown,
                        label = Label}};
        {error, Reason} ->
            error_logger:error_msg(
              "failed to start ~s on ~s:~p - ~p~n",
              [Label, inet_parse:ntoa(IPAddress), Port, Reason]),
            {stop, {cannot_listen, IPAddress, Port, Reason}}
    end.

q里有一个技巧,如果要@环Nơ执行某个函数FQ可以通过lists:foreachl合lists:duplicate(N,dummy)来处理?br />
lists:foreach(fun(_)-> F() end,lists:duplicate(N,dummy)).

3?strong>simple_one_for_one{略的?/strong>Q可以看到对于tcp_client_sup和tcp_acceptor_sup都采用了simple_one_for_one{略Q而非普通的one_fo_oneQ这是ؓ什么呢Q?br /> q牵扯到simple_one_for_one的几个特点:
1)simple_one_for_one内部保存child是用dictQ而其他策略是使用listQ因此simple_one_for_one更适合child频繁创徏销毁、需要大量childq程的情况,具体来说例如|络q接的频J接入断开?br /> 2)使用了simple_one_for_one后,无法调用terminate_child/2 delete_child/2 restart_child/2

3)start_child/2 对于simple_one_for_one来说Q不必传入完整的child spectQ传入参数listQ会自动q行参数合ƈ?strong>在一个地方定义好child spec之后Q其他地方只要start_child传入参数卛_启动childq程Q简化child都是同一cdq程情况下的~程?br />
? rabbitmq中,tcp_acceptor_sup的子q程都是tcp_acceptorq程Q在tcp_listener中是启动? ConcurrentAcceptorCount个tcp_acceptor子进E,通过supervisor:start_child/2ҎQ?br />
%%创徏ConcurrentAcceptorCount个ƈ发acceptor
            lists:foreach(fun (_) ->
                                  {ok, _APid} = supervisor:start_child(
                                                  AcceptorSup, [
LSock])
                          end,
                          lists:duplicate(ConcurrentAcceptorCount, dummy)),

注意刎ͼq里调用的start_child只传入了LSock一个参敎ͼ另一个参数CallBack是在定义child spec的时候传入的Q参见tcp_acceptor_sup.erl:
init(Callback) ->
    {ok, {{simple_one_for_one, 10, 10},
          [{tcp_acceptor, {tcp_acceptor, start_link, [Callback]},
            transient, brutal_kill, worker, [tcp_acceptor]}]}}.

Erlang内部自动为simple_one_for_one做了参数合ƈQ最后调用的是tcp_acceptor的init/2:

init({Callback, LSock}) ->
    case prim_inet:async_accept(LSock, -1) of
        {ok, Ref} -> {ok, #state{callback=Callback, sock=LSock, ref=Ref}};
        Error -> {stop, {cannot_accept, Error}}
    end.

对于tcp_client_sup的情늱|tcp_client_sup监控的子q程都是rabbit_readercdQ在 rabbit_networking.erl中启动tcp_listenner传入的处理connect事g的回调方法是? rabbit_networking:start_client/1:

start_tcp_listener(Host, Port) ->
    start_listener(Host, Port, "TCP Listener",
                   %回调的MFA
                   {?MODULE, start_client, []}).

start_client(Sock) ->
    {ok, Child} = supervisor:start_child(rabbit_tcp_client_sup, []),
    ok = rabbit_net:controlling_process(Sock, Child),
    Child ! {go, Sock},
    Child.

start_client调用了supervisor:start_child/2来动态启动rabbit_readerq程?br />
4?strong>协议的解析,消息的读?/strong>q部分也非常巧妙Q这一部分主要在rabbit_reader.erl中,对于协议的解析没有采用gen_fsmQ而是实现了一个y妙的状态机机制,核心代码在mainloop/4中:
%启动一个连?br /> start_connection(Parent, Deb, ClientSock) ->
    process_flag(trap_exit, true),
    {PeerAddressS, PeerPort} = peername(ClientSock),
    ProfilingValue = setup_profiling(),
    try
        rabbit_log:info("starting TCP connection ~p from ~s:~p~n",
                        [self(), PeerAddressS, PeerPort]),
         %延时发送握手协?br />         Erlang:send_after(?HANDSHAKE_TIMEOUT * 1000, self(),
                          handshake_timeout),
        %q入d@环,更换callback模块Q魔法就在这个switch_callback
        mainloop(Parent, Deb, switch_callback(
                                #v1{sock = ClientSock,
                                    connection = #connection{
                                      user = none,
                                      timeout_sec = ?HANDSHAKE_TIMEOUT,
                                      frame_max = ?FRAME_MIN_SIZE,
                                      vhost = none},
                                    callback = uninitialized_callback,
                                    recv_ref = none,
                                    connection_state = pre_init},
                                %%注意到这里,handshake是我们的回调模块,8是希望接收的数据长度,AMQP协议头的八个字节?/strong>
                                handshake, 8))

法在switch_callbackq个Ҏ上:
switch_callback(OldState, NewCallback, Length) ->
    %发v一个异步recvhQ请求Length字节的数?br />     Ref = inet_op(fun () -> rabbit_net:async_recv(
                              OldState#v1.sock, Length, infinity) end),
    %更新状态,替换ref和处理模?br />     OldState#v1{callback = NewCallback,
                recv_ref = Ref}.


异步接收Length个数据,如果有,erlang会通知你处理。处理模块是什么概念呢Q其实就是一个状态的概念Q表C当前协议解析进行到哪一步,起一个label的作用,看看mainloop/4中的应用Q?br />
mainloop(Parent, Deb, State = #v1{sock= Sock, recv_ref = Ref}) ->
    %%?LOGDEBUG("Reader mainloop: ~p bytes available, need ~p~n", [HaveBytes, WaitUntilNBytes]),
    receive
        %%接收到数据,交给handle_input处理,注意handle_input的第一个参数就是callback
        {inet_async, Sock, Ref, {ok, Data}} ->
            %handle_input处理
            {State1, Callback1, Length1} =
                handle_input(State#v1.callback, Data,
                             State#v1{recv_ref = none}),

            %更新回调模块Q再ơ发起异步请求,q进入主循环
            mainloop(Parent, Deb,
                     switch_callback(State1, Callback1, Length1));


handle_input有多个分支,每个分支都对应一个处理模块,例如我们刚才提到的握手协议:

%handshake模块Q注意到W一个参敎ͼW二个参数就是我们得到的数据
handle_input(handshake, <<"AMQP",1,1,ProtocolMajor,ProtocolMinor>>,
             State = #v1{sock = Sock, connection = Connection}) ->
     %协议是否兼?br />     case check_version({ProtocolMajor, ProtocolMinor},
                       {?PROTOCOL_VERSION_MAJOR, ?PROTOCOL_VERSION_MINOR}) of
        true ->
            {ok, Product} = application:get_key(id),
            {ok, Version} = application:get_key(vsn),
            %兼容的话Q进入connections startQ协商参?br />             ok = send_on_channel0(
                   Sock,
                   #'connection.start'{
                     version_major = ?PROTOCOL_VERSION_MAJOR,
                     version_minor = ?PROTOCOL_VERSION_MINOR,
                     server_properties =
                     [{list_to_binary(K), longstr, list_to_binary(V)} ||
                         {K, V} <-
                             [{"product",     Product},
                              {"version",     Version},
                              {"platform",    "                               {"copyright",   ?COPYRIGHT_MESSAGE},
                              {"information", ?INFORMATION_MESSAGE}]],
                     mechanisms = <<"PLAIN AMQPLAIN">>,
                     locales = <<"en_US">> }),
            {State#v1{connection = Connection#connection{
                                     timeout_sec = ?NORMAL_TIMEOUT},
                      connection_state = starting},
             frame_header, 7};
         %否则Q断开q接Q返回可以接受的协议
        false ->
            throw({bad_version, ProtocolMajor, ProtocolMinor})
    end;

    其他协议的处理也是类|通过动态替换callback的方式来模拟状态机做协议的解析和数据的接收Q真的很巧妙Q让我们体会到Erlang的魅力,FP的魅力?br />
5、序列图Q?/strong>
1Qtcp server的启动过E:

2Q一个clientq接上来的处理过E:


    结Q从上面的分析可以看?rabbitmq的网l层是非常健壮和高效的,通过层层监控Q对每个可能出现的风险点都做了考虑Qƈ且利用了prim_net模块做异步IO处理。分层也是很清晰Q将业务处理模块隔离到client_sup监控下的子进E,网l处理细节和业务逻辑分离。在协议的解析和业务处理上虽然没有采用gen_fsmQ但是也实现了一套类似的状态机机制Q通过动态替换Callback来模拟状态的变迁Q非常y妙。如果你要实C个tcp serverQ强烈推荐从rabbitmq中扣个网l层Q你只需要实现自q业务处理模块卛_拥有一个高效、健壮、分层清晰的TCP服务器?br />

dennis 2009-11-29 12:00 发表评论
]]>
Erlang Web Shell(update)http://m.tkk7.com/killme2008/archive/2009/11/19/302967.htmldennisdennisThu, 19 Nov 2009 11:22:00 GMThttp://m.tkk7.com/killme2008/archive/2009/11/19/302967.htmlhttp://m.tkk7.com/killme2008/comments/302967.htmlhttp://m.tkk7.com/killme2008/archive/2009/11/19/302967.html#Feedback0http://m.tkk7.com/killme2008/comments/commentRss/302967.htmlhttp://m.tkk7.com/killme2008/services/trackbacks/302967.html   
   下午搞了?a >Erlang web shellQ可以在web面上像eshell那样q行交互式的Erlang~程Q方便学习和试。这样一来,一?a >erlwsh可以服务多个clientQ只要你有网l和览器,随时随地可以敲上几行erlang看看l果。代码很单,׃多说了,有兴的看看Q通过mochiweb的http chunk~码Qclient通过Ajax Post方式提交。眼见ؓ实,看看q行截图Q?br />




    工程在google code上: http://code.google.com/p/erlwsh/
   
    安装很简单,首先保你已l安装了ErlangQ接下来Q?br />
svn checkout http://erlwsh.googlecode.com/svn/trunk/ erlwsh-read-only
cd erlwsh-read-only
scripts/install_mochiweb.sh
make
./start.sh

    因ؓ需要用mochiwebQ所以提供了下蝲q自动安装的脚本Q这是litaocheng的大作。启动后讉K http://localhost:8000/shell 卛_Qhave fun.





dennis 2009-11-19 19:22 发表评论
]]>
ets和dets的效率徏?/title><link>http://m.tkk7.com/killme2008/archive/2007/09/27/148764.html</link><dc:creator>dennis</dc:creator><author>dennis</author><pubDate>Thu, 27 Sep 2007 08:33:00 GMT</pubDate><guid>http://m.tkk7.com/killme2008/archive/2007/09/27/148764.html</guid><wfw:comment>http://m.tkk7.com/killme2008/comments/148764.html</wfw:comment><comments>http://m.tkk7.com/killme2008/archive/2007/09/27/148764.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://m.tkk7.com/killme2008/comments/commentRss/148764.html</wfw:commentRss><trackback:ping>http://m.tkk7.com/killme2008/services/trackbacks/148764.html</trackback:ping><description><![CDATA[   ets表的底层是由哈希表实现的,不过ordered_set例外,它是由^衡二叉树实现的?所以不是插入q是查找,set的效率要比ordered_set?采用setq是ordered_set取决于你的需求,当你需要一个有序的集合Ӟ昄应当采用ordered_set模式?br /> <br /> duplicate_bag要比bag的效率要? 因ؓbag要和原来的记录比较是否有相同的记录已l插? 如果数据量很?相同的记录越?bag的效率就差. <br /> <br /> 一张ets表是由创建它的进E所拥有, 当此q程调用ets:delete或者进E终止的时? ets表就会被删除. <br /> <br /> 一般情况下, 插入一个元l到一张ets表中, 所有代表这个元l的l构都会被从process的堆栈中,复制到ets表中; 当查找一条记录时, l果tuple从ets表中复制到进E的堆栈中?<br /> <br /> 但是large binaries却不是这? 它们被存入自已所拥有的off-heap area中。这个区域可以被多个process,ets?和binaries所׃n。它由引用计数的垃圾回收{略理, q个{略会跟t到底有多少个process/ets?binaries引用了这个large binaries. 如果引用Cؓ0的话, 此大型二q制数据׃被垃圑֛收掉. <br /> <br /> 看v来很复杂, 实际l论是: 两进E间发送包含大型binary数据的消息其实费用很? 往ets表插入binarycd元组也很划算。我们应该尽可能采用binaries来实现字W串或无cd的大数据?<img src ="http://m.tkk7.com/killme2008/aggbug/148764.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://m.tkk7.com/killme2008/" target="_blank">dennis</a> 2007-09-27 16:33 <a href="http://m.tkk7.com/killme2008/archive/2007/09/27/148764.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Erlang之IO~程http://m.tkk7.com/killme2008/archive/2007/09/27/148747.htmldennisdennisThu, 27 Sep 2007 08:03:00 GMThttp://m.tkk7.com/killme2008/archive/2007/09/27/148747.htmlhttp://m.tkk7.com/killme2008/comments/148747.htmlhttp://m.tkk7.com/killme2008/archive/2007/09/27/148747.html#Feedback2http://m.tkk7.com/killme2008/comments/commentRss/148747.htmlhttp://m.tkk7.com/killme2008/services/trackbacks/148747.html file模块Q打开、读、写、关闭文件已l操作目录的Ҏ基本都在q里

filename模块Q提供^台独立方式用于操U|件名

filelib模块Qfile模块的扩展,提供了更多的实用工具Q在file模块基础上构?br />
io模块Q一pd用于操作打开的文件的ҎQ解析格式、格式化输出{等?br />
1.打开文gQ?br /> {ok,F}=file:open("data1.dat",read). %L式打开
{ok,F}=file:open("data1.dat",write). %写模?br /> {ok,F}=file:open("data1.dat",[read,write]). %诅R写、二q制模式

支持的所有模式参见文档?br />
2.dQ?br /> (1)如果以一个Erlang term的方式读取,采用:
io:read(F,'').
其中W二个参数是提示W,用于在标准输入时作ؓ提示?br /> q个Ҏ有一个变形read/3
read(IoDevice, Prompt, StartLine)
W三个参数用于指定开始行数?br />
(2)如果是按字节dQ文件必Lraw模式打开采用Q?br /> {ok, Data}=file:read(F,100).

(3)按行dQ?br /> io:get_line(F, '').

(4)d整个文g的内容:
{ok,Binary}=file:read_file("data1.dat").
注意q回的是一个binarycd

(5)随机dQ?br /> {ok,Binary}=file:pread(F, 22, 46).

其中W二个参数是开始位|,W三个参数是d的长度,q回的也是binarycd?br />
3.写入文gQ?br /> (1)采用io:format/3ҎQ?br /> {ok, S} = file:open("test2.dat", write).
io:format(S, "~s~n", ["Hello readers"]).
io:format(S, "~w~n", [123]).

其中的~开头的字符是一个个格式化命令,比如常见的:
~c   anscii?br /> ~f   点?br /> ~s   字符?br /> ~w   Erlang term
~p   与~wcMQ不q当多行时将自动换行
~n   昄Q换行符

Q?Q写入整个文Ӟ
file:write_file(File, IO)

其中IO可以为list、integer或者binarycd

Q?Q随机写入:
file:pwrite(F, 10, <<"new">>)

4.关闭文g:
file:close(F).

5.目录操作Q?br /> 都是linux命o风格的操作,
cd("/home/dennis/").  %q入目录
file:list_dir(".").   %列出当前目录文g
file:make_dir("test").  %创徏test目录
file:del_dir("test").   %删除test目录

6.获取文g信息Q比如文件大,最后修Ҏ间等{。调用file:read_file_info/1ҎQ该Ҏq回一个file_info记录cdQ里面拥有文件的具体信息Q比如type、size{?br /> {ok, Facts} =file:read_file_info(File).
io:format("~s~n",{Facts#file_info.type, Facts#file_info.size}).

7.复制和删除文Ӟ
file:copy(Source, Destination).
file:delete(File).

    q个W记仅仅记录了一些常用到的方法,一些高U的工具Ҏq没有涉及,具体参考Erlang的文档?br />





dennis 2007-09-27 16:03 发表评论
]]>
单的web server性能试http://m.tkk7.com/killme2008/archive/2007/08/29/141036.htmldennisdennisWed, 29 Aug 2007 10:10:00 GMThttp://m.tkk7.com/killme2008/archive/2007/08/29/141036.htmlhttp://m.tkk7.com/killme2008/comments/141036.htmlhttp://m.tkk7.com/killme2008/archive/2007/08/29/141036.html#Feedback4http://m.tkk7.com/killme2008/comments/commentRss/141036.htmlhttp://m.tkk7.com/killme2008/services/trackbacks/141036.html阅读全文

dennis 2007-08-29 18:10 发表评论
]]>
Erlang ring benchmarkhttp://m.tkk7.com/killme2008/archive/2007/08/04/134417.htmldennisdennisSat, 04 Aug 2007 09:46:00 GMThttp://m.tkk7.com/killme2008/archive/2007/08/04/134417.htmlhttp://m.tkk7.com/killme2008/comments/134417.htmlhttp://m.tkk7.com/killme2008/archive/2007/08/04/134417.html#Feedback0http://m.tkk7.com/killme2008/comments/commentRss/134417.htmlhttp://m.tkk7.com/killme2008/services/trackbacks/134417.htmlq里
    不过我分析了q个试里的Erlang代码Q存在问题,q没有完成所有的循环Q进E就l束了,q对比较l果有较大的影响。原始代码如下:

-module(zog).

%% This is a test program that first creates N processes (that are
%% "connected" in a ring) and then sends M messages in that ring.
%%
%% - September 1998
%% - roland


-export([start/0, start/1, start/2]).

-export([run/2, process/1]). % Local exports - ouch

start() -> start(16000).

start(N) -> start(N, 1000000).

start(N, M) -> spawn(?MODULE, run, [N, M]).


run(N, M) when N < 1 ->
io:format("Must be at least 1 process~n", []),
0.0;
run(N, M) ->
statistics(wall_clock),

Pid = setup(N-1, self()),

{_,T1} = statistics(wall_clock),
io:format("Setup : ~w s", [T1/1000]),
case N of
1 -> io:format(" (0 spawns)~n", []);
_ -> io:format(" (~w us per spawn) (~w spawns)~n",
[1000*T1/(N-1), N-1])
end,
statistics(wall_clock),

Pid ! M,
K = process(Pid),

{_,T2} = statistics(wall_clock),
Time = 1000*T2/(M+K),
io:format("Run : ~w s (~w us per msg) (~w msgs)~n",
[T2/1000, Time, (M+K)]),

Time.

setup(0, OldPid) ->
OldPid;
setup(N, OldPid) ->
NewPid = spawn(?MODULE, process, [OldPid]),
setup(N-1, NewPid).


process(Pid) ->
receive
M ->
Pid ! M-1,
if
M < 0 -> -M;
true -> process(Pid)
end
end.
  我将process修改一?/span>Q?br>
process(Pid) ->
receive
M ->
Pid ! M-1,
io:format("form ~w to ~w~n",[self(),Pid]),
if
M < 0 -> -M;
true -> process(Pid)
end
end.
然后执行下zog:run(3,3)Q?span style="font-weight: bold;">你将发现消息l了两圈q束了Q第三圈Ҏ没有q行
Q不知道试者是什么用意?span style="font-weight: bold;">依照现在的执?00万次消息传送竟然只需?毫秒Q我修改了下了下代码如下Q?br>-module(zog).

%% This is a test program that first creates N processes (that are
%% "connected" in a ring) and then sends M messages in that ring.
%%
%% - September 1998
%% - roland
-export([start/0, start/1, start/2]).

-export([run/2, process/2]).                    % Local exports - ouch

start() -> start(16000).

start(N) -> start(N, 1000000).

start(N, M) -> spawn(?MODULE, run, [N, M]).


run(N, M) when N < 1 ->
    io:format("Must be at least 1 process~n", []),
    0.0;
run(N, M) ->
    statistics(wall_clock),
    Limit=N-N*M+1+M,
    Pid = setup(N-1,Limit,self()),

    {_,T1} = statistics(wall_clock),
    io:format("Setup : ~w s", [T1/1000]),
    case N of
        1 -> io:format(" (0 spawns)~n", []);
        _ -> io:format(" (~w us per spawn) (~w spawns)~n",
                       [1000*T1/(N-1), N-1])
    end,
    statistics(wall_clock),
  %  io:format("run's Pid=~w~n",[Pid]),
    Pid ! M,
    K = process(Pid,Limit),
  %  io:format("run's K=~w~n",[K]),

    {_,T2} = statistics(wall_clock),
    Time = 1000*T2/(M+K),
    io:format("Run   : ~w s (~w us per msg) (~w msgs)~n",
              [T2/1000, Time, (M+K)]),
 T2/1000.

setup(0,Limit, OldPid) ->
    OldPid;
setup(N,Limit, OldPid) ->
    NewPid = spawn(?MODULE, process, [OldPid,Limit]),
    setup(N-1, Limit,NewPid).


process(Pid,Limit) ->
    receive
        M ->
            Pid ! M-1,
         %   io:format("from ~w to ~w and M=~w~n",[self(),Pid,M]),
            if
                M <Limit  -> -M;
                true   -> process(Pid,Limit)
            end
    end.
修改之后Q执行zog:run(3000,1000Q,也就?000个进E,1000ơ消息@环,d300万次消息传递,l果?.5U左叻Iq也是相当惊人的l果。有人用haskell和scheme各实C一个版本,有兴的看看q里?a >q里




dennis 2007-08-04 17:46 发表评论
]]>
Erlang入门Q五Q——补?/title><link>http://m.tkk7.com/killme2008/archive/2007/07/24/132011.html</link><dc:creator>dennis</dc:creator><author>dennis</author><pubDate>Tue, 24 Jul 2007 03:23:00 GMT</pubDate><guid>http://m.tkk7.com/killme2008/archive/2007/07/24/132011.html</guid><wfw:comment>http://m.tkk7.com/killme2008/comments/132011.html</wfw:comment><comments>http://m.tkk7.com/killme2008/archive/2007/07/24/132011.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://m.tkk7.com/killme2008/comments/commentRss/132011.html</wfw:commentRss><trackback:ping>http://m.tkk7.com/killme2008/services/trackbacks/132011.html</trackback:ping><description><![CDATA[    暂时搞不到《Programming <a title="" >Erlang</a>》,最q就一直在看Erlang自带的例子和Reference Manual。基语法斚w有一些过去遗漏或者没有注意的Q断断箋l仅C此?br><br><span style="font-weight: bold;">1。Erlang的保留字</span>有:<br> <p>after and andalso band begin bnot bor bsl bsr bxor case catch cond div end fun if let not of or orelse query receive rem try when xor<a name="1.6"><!-- Empty --></a> </p> 基本都是些用于逻辑q算、位q算以及Ҏ表达式的W号<br><br><span style="font-weight: bold;">2.Erlang的类?/span>Q除了在前面入门一提到的类型外Q还包括Q?br>1)BinaryQ用于表C某D|知类型的内存区域<br>比如Q?br>1> <strong> <<10,20>>.</strong> <br><<10,20>> <br>2> <strong> <<"ABC">>.</strong><br> <<65,66,67>> <br><br>2QReferenceQ通过调用mk_ref/0产生的运行时的unique term<br><br>3)StringQ字W串QErlang中的字符串用双引号包括v来,其实也是list。编译时期,两个邻近的字W串被q接hQ比?string" "42" {h?"string42"<br><br>4)RecordQ记录类型,与c语言中的structcMQ模块可以通过-record属性声明,比如Q?br>-module(person). <br>-export([new/2]).<br>-record(person, {name, age}). <br>new(Name, Age) -><br>     #person{name=Name, age=Age}. <br>1> <strong> person:new(dennis, 44).</strong> <br>{person,dennis,44} <br> 在编译后其实已经被{化ؓtuple。可以通过Name#person.name来访问Name Record的name属性?br><br><span style="font-weight: bold;">3.模块的预定义属?/span>Q?br><code>-module(Module).</code>    声明模块名称Q必M文g名相?br><code>-export(Functions).</code>   指定向外界导出的函数列表<br><code>-import(Module,Functions).</code>   引入函数Q引入的函数可以被当作本地定义的函数使用<br><code>-compile(Options).</code>     讄~译选项Q比如export_all<br>-vsn(Vsn).         模块版本Q设|了此项Q可以通过<code>beam_lib:version/1</code> 获取此项信息<br>可以通过-include?include_lib来包含文Ӟ两者的区别是include-lib不能通过l对路径查找文gQ而是在你当前Erlang的lib目录q行查找?br><br><span style="font-weight: bold;">4.try表达?/span>Qtry表达式可以与catchl合使用Q比如:<br> <pre>try Expr<br>catch<br> throw:Term -> Term;<br> exit:Reason -> {'EXIT',Reason}<br> error:Reason -> {'EXIT',{Reason,erlang:get_stacktrace()}}<br>end<br><br>不仅如此Qtryq可以与afterl合使用Q类似java中的try..finallyQ用于进行清除作用,比如Q?br>termize_file(Name) -> {ok,F} = file:open(Name, [read,binary]), try {ok,Bin} = file:read(F, 1024*1024), binary_to_term(Bin) after file:close(F) end. <br><br><span style="font-weight: bold;">5.列表推断</span>QList ComprehensionsQ,函数式语aҎ之一QErlang中的语法cMQ?br>[Expr || Qualifier1,...,QualifierN] Expr可以是Q意的表达式,而Qualifier是generator或者filter。还是各举例子说明下?br>1> <strong> [X*2 || X <- [1,2,3]].</strong> [2,4,6]<br><br>2> L=[1,2,3,4,5,6,7].<br>[1,2,3,4,5,6,7]<br> <pre>3> <span style="font-weight: bold;">[X|X<-L,X>=3].<br>[</span>3,4,5,6,7]<br><br>再看几个比较L例子Q来自Programming <a title="" >Erlang</a>Q?br>比如<span style="font-weight: bold;">快速排?/span>Q?br>-module(qsort).<br>-export([qsort/1]).<br>qsort([])->[];<br>qsort([Pivot|T])-><br>  qsort([X||X<-T,X<Pivot])<br>   ++ [Pivot] ++ <br>  qsort([X||X<-T,X>=Pivot]).<br><br>搜烦<span style="font-weight: bold;">勾股数组</span>Q?br>%勾股数组<br>-module(pythag).<br>-export([pythag/1]).<br>pythag(N)-><br>    L=lists:seq(1,N),<br>    Square=fun(X) when is_number(X)->X*X end,<br>    [{A,B,C}||<br>        A<-L,<br>        B<-L,<br>        C<-L,<br>        A+B+C=<N,<br>        Square(A)+Square(B)=:=Square(C)].<br>列表推断大大减你的敲击键盘的ơ数?br>  <br><span style="font-weight: bold;">6.?/span>Q定义常量或者函数等{,语法如下Q?br>-define(Const, Replacement). -define(Func(Var1,...,VarN), Replacement). <br>使用的时候在宏名前加个问PQ比?ConstQReplacement插入宏出现的位|。系l预定义了一些宏:<br><code><span style="font-weight: bold;">?MODULE </span> 表示当前模块?br><br><span style="font-weight: bold;">?MODULE_STRING</span> 同上Q但是以字符串Ş?br></code><span style="font-weight: bold;">?FILE</span> 当前模块的文件名<br><span style="font-weight: bold;">?LINE</span> 调用的当前代码行?br><span style="font-weight: bold;">?MACHINE</span> 机器?br><br>Erlang的宏与C语言的宏很相|同样有宏指示W,包括Q?br><dl><dt><code>-undef(Macro).</code> </dt><dd>取消宏定? </dd><dt><code>-ifdef(Macro).</code> </dt><dd>当宏Macro有定义的时候,执行以下代码 </dd><dt><code>-ifndef(Macro).</code> </dt><dd>同上Q反? </dd><dt><code>-else.</code> </dt><dd>接在ifdef或者ifndef之后Q表CZ满前者条件时执行以下代码 <br></dd><dt><code>-endif.</code> </dt><dd>ifl止W?/dd></dl>假设?define(Square(X),X*X).用于计算qxQ那??X返回X表达式的字符串Ş式,cMC语言?arg<br><br>一个简单的宏例子:<br> <div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #000000;">-</span><span style="color: #000000;">module(macros_demo).<br></span><span style="color: #000000;">-</span><span style="color: #000000;">ifdef(debug).<br></span><span style="color: #000000;">-</span><span style="color: #000000;">define(LOG(X), io:format(</span><span style="color: #800000;">"</span><span style="color: #800000;">{~p,~p}: ~p~n</span><span style="color: #800000;">"</span><span style="color: #000000;">, [?MODULE,?LINE,X])).<br></span><span style="color: #000000;">-</span><span style="color: #0000ff;">else</span><span style="color: #000000;">.<br></span><span style="color: #000000;">-</span><span style="color: #000000;">define(LOG(X), true).<br></span><span style="color: #000000;">-</span><span style="color: #000000;">endif.<br></span><span style="color: #000000;">-</span><span style="color: #000000;">define(Square(X),X</span><span style="color: #000000;">*</span><span style="color: #000000;">X).<br></span><span style="color: #000000;">-</span><span style="color: #000000;">compile(export_all).<br>test()</span><span style="color: #000000;">-></span><span style="color: #000000;"><br>    A</span><span style="color: #000000;">=</span><span style="color: #000000;">3</span><span style="color: #000000;">,<br>    ?LOG(A),<br>    B</span><span style="color: #000000;">=</span><span style="color: #000000;">?Square(A),<br>    io:format(</span><span style="color: #800000;">"</span><span style="color: #800000;">square(~w) is ~w~n</span><span style="color: #800000;">"</span><span style="color: #000000;">,[A,B]).</span></div> 当编译时不开启debug选项的时候:<br>17> c(macros_demo).<br>{ok,macros_demo}<br>18> macros_demo:test().<br>square(3) is 9<br><br>当编译时开启debug之后Q?br><br>19> c(macros_demo,{d,debug}).<br>{ok,macros_demo}<br>20> macros_demo:test().<br><span style="font-weight: bold;">{macros_demo,11}: 3</span><br>square(3) is 9<br>ok<br><br>可以看到LOG的输ZQ行数、模块名以及参数<br> 7?span style="font-weight: bold;">Process Dictionary</span>Q每个进E都有自qprocess dictionaryQ用于存储这个进E内的全局变量Q可以通过下列<br>BIFs操作Q?br>put(Key, Value)<br>get(Key)<br>get()<br>get_keys(Value)<br>erase(Key)<br>erase()<br><br><span style="font-weight: bold;">8、关于分布式~程</span>Q需要补充的几点<br>1Q节点之间的q接默认是transitiveQ也是当节点Aq接了节点BQ节点Bq接了节点CQ那么节点A也与节点C互相q接<br>可以通过启动节点时指定参?connect_all false来取消默认行?br><br>2Q隐藏节点,某些情况下,你希望连接一个节点而不去连接其他节点,你可以通过在节点启动时指定-hidden选项<br>来启动一个hidden node。在此情况下Q通过nodes()查看所有连接的节点不会出现隐藏的节点Q想看到隐藏的节?br>可以通过nodes(hidden)或者nodes(connected)来查看?br><br>完整的erl选项如下Q?br> <table border="1" cellpadding="2" cellspacing="0"> <tbody> <tr> <td align="left" valign="center"><code>-connect_all false</code> </td> <td align="left" valign="center">上面已经解释? </td> </tr> <tr> <td align="left" valign="center"><code>-hidden</code> </td> <td align="left" valign="center">启动一个hidden node<br> </td> </tr> <tr> <td align="left" valign="center"><code>-name Name</code> </td> <td align="left" valign="center">启动一个系l成点,使用long name. </td> </tr> <tr> <td align="left" valign="center"><code>-setcookie Cookie</code> </td> <td align="left" valign="center">?code><a title="" >Erlang</a>:set_cookie(node(), Cookie)</code>.相同Q设|magic cookie<br> </td> </tr> <tr> <td align="left" valign="center"><code>-sname Name</code> </td> <td align="left" valign="center">启动一个Erlangpȝ作ؓ节点Q用short name <br></td> </tr> </tbody> </table> <br>注意,<span style="font-weight: bold;">short name启动的节Ҏ无法与long name节点通信?/span>?br><br><span style="font-weight: bold;">9.一个小l节Q在Erlang中小于等于是?<表示Q而不是一般语a中的<=语法Q我犯过错误的地方,同样Q不{于都是?P而不?/span><br style="font-weight: bold;"><span style="font-weight: bold;">!,比如/=?/=?/span><br><br><span style="font-weight: bold;">10.and or 和andalso orelse的区?/span><br><br>and和or会计两边的表达式,而andalso和orelse的求值采用短路机Ӟ比如exp1 andalso exp2Q当exp1q回false之后Q就不会L?br>exp2Q而是直接q回falseQ而exp1 and exp2会对exp1和exp2都进行求|or与orelse也类伹{?br> <br>今天?a >erlang-china</a>下到了《Programming <a title="" >Erlang</a>》,准备打印一份看看,q入OTP的学习? <br><br></pre> <br>  <br>  <br></pre> <br><br><br><br><br><img src ="http://m.tkk7.com/killme2008/aggbug/132011.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://m.tkk7.com/killme2008/" target="_blank">dennis</a> 2007-07-24 11:23 <a href="http://m.tkk7.com/killme2008/archive/2007/07/24/132011.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>从一个小例子出发之ruby、scheme和Erlang的简单比?/title><link>http://m.tkk7.com/killme2008/archive/2007/07/15/130384.html</link><dc:creator>dennis</dc:creator><author>dennis</author><pubDate>Sun, 15 Jul 2007 08:11:00 GMT</pubDate><guid>http://m.tkk7.com/killme2008/archive/2007/07/15/130384.html</guid><wfw:comment>http://m.tkk7.com/killme2008/comments/130384.html</wfw:comment><comments>http://m.tkk7.com/killme2008/archive/2007/07/15/130384.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://m.tkk7.com/killme2008/comments/commentRss/130384.html</wfw:commentRss><trackback:ping>http://m.tkk7.com/killme2008/services/trackbacks/130384.html</trackback:ping><description><![CDATA[    Lich Ray写了个帖子?a >函数式编E语a曲高和寡Q?/a>》,用快速排序的例子来说明函数式~程在表达思想斚w比命令式语言更容易,其实q一Ҏ庸置疑,如果你正在读或者读qSICP的话。文中给了haskell、scheme和javascript的实C子,我也凑趣写了个Erlang版本Qhaskell我不了解׃说了Q其他实现分别如下:<br>schemeQ?br> <div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #000000;">(define (qsort ls)  <br>     (</span><span style="color: #0000ff;">if</span><span style="color: #000000;"> (null</span><span style="color: #000000;">?</span><span style="color: #000000;"> ls) </span><span style="color: #000000; font-weight: bold;">'</span><span style="color: #000000; font-weight: bold;">()  <br>         (let  <br>             ((x (car ls))  <br>             (xs (cdr ls)))  <br>             (let   <br>                 ((lt (filter (lambda (y) (< y x)) xs))  <br>                 (st (filter (lambda (y) (>= y x)) xs)))  <br>                 (append (qsort lt) (list x) (qsort st))))))  </span></div> <br>javascript:<br> <div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #000000;">    </span><span style="color: #000000;">//</span><span style="color: #000000;"> 把要用到的表辑ּ抽象出来  <br>    Array</span><span style="color: #000000;">.</span><span style="color: #0000ff;">prototype</span><span style="color: #000000;">.</span><span style="color: #000000;">head </span><span style="color: #000000;">=</span><span style="color: #000000;"> function () {  <br>        </span><span style="color: #0000ff;">return</span><span style="color: #000000;"> this[</span><span style="color: #800000;">0</span><span style="color: #000000;">];  <br>    }  <br>      <br>    Array</span><span style="color: #000000;">.</span><span style="color: #0000ff;">prototype</span><span style="color: #000000;">.</span><span style="color: #000000;">tail </span><span style="color: #000000;">=</span><span style="color: #000000;"> function () {  <br>        </span><span style="color: #0000ff;">return</span><span style="color: #000000;"> this</span><span style="color: #000000;">.</span><span style="color: #000000;">slice(</span><span style="color: #800000;">1</span><span style="color: #000000;">);  <br>    }  <br>      <br>   Array</span><span style="color: #000000;">.</span><span style="color: #0000ff;">prototype</span><span style="color: #000000;">.</span><span style="color: #000000;">filter </span><span style="color: #000000;">=</span><span style="color: #000000;"> function (proc) {  <br>       var tmpArr </span><span style="color: #000000;">=</span><span style="color: #000000;"> [];  <br>       </span><span style="color: #0000ff;">for</span><span style="color: #000000;"> (var i </span><span style="color: #000000;">=</span><span style="color: #000000;"> </span><span style="color: #800000;">0</span><span style="color: #000000;">; i </span><span style="color: #000000;"><</span><span style="color: #000000;"> this</span><span style="color: #000000;">.</span><span style="color: #0000ff;">length</span><span style="color: #000000;">; i</span><span style="color: #000000;">++</span><span style="color: #000000;">)  <br>       </span><span style="color: #0000ff;">if</span><span style="color: #000000;"> (proc(this[i]) </span><span style="color: #000000;">==</span><span style="color: #000000;"> true)  <br>           tmpArr</span><span style="color: #000000;">.</span><span style="color: #0000ff;">push</span><span style="color: #000000;">(this[i]);  <br>       </span><span style="color: #0000ff;">return</span><span style="color: #000000;"> tmpArr;  <br>   }  <br>   Array</span><span style="color: #000000;">.</span><span style="color: #0000ff;">prototype</span><span style="color: #000000;">.</span><span style="color: #000000;">qsort </span><span style="color: #000000;">=</span><span style="color: #000000;"> function () {  <br>       </span><span style="color: #0000ff;">if</span><span style="color: #000000;"> (this </span><span style="color: #000000;">==</span><span style="color: #000000;"> false) </span><span style="color: #0000ff;">return</span><span style="color: #000000;"> []  <br>        var x</span><span style="color: #000000;">,</span><span style="color: #000000;"> xs</span><span style="color: #000000;">,</span><span style="color: #000000;"> lt</span><span style="color: #000000;">,</span><span style="color: #000000;"> st  <br>       x </span><span style="color: #000000;">=</span><span style="color: #000000;"> this</span><span style="color: #000000;">.</span><span style="color: #000000;">head()  <br>        xs </span><span style="color: #000000;">=</span><span style="color: #000000;"> this</span><span style="color: #000000;">.</span><span style="color: #000000;">tail()  <br>        lt </span><span style="color: #000000;">=</span><span style="color: #000000;"> xs</span><span style="color: #000000;">.</span><span style="color: #000000;">filter(function (y) {</span><span style="color: #0000ff;">return</span><span style="color: #000000;"> y </span><span style="color: #000000;"><</span><span style="color: #000000;"> x})  <br>        st </span><span style="color: #000000;">=</span><span style="color: #000000;"> xs</span><span style="color: #000000;">.</span><span style="color: #000000;">filter(function (y) {</span><span style="color: #0000ff;">return</span><span style="color: #000000;"> y </span><span style="color: #000000;">>=</span><span style="color: #000000;"> x})  <br>        </span><span style="color: #0000ff;">return</span><span style="color: #000000;"> lt</span><span style="color: #000000;">.</span><span style="color: #000000;">qsort()</span><span style="color: #000000;">.</span><span style="color: #000000;">concat([x]</span><span style="color: #000000;">,</span><span style="color: #000000;"> st</span><span style="color: #000000;">.</span><span style="color: #000000;">qsort())  <br>    }  </span></div> 用Erlang的话QErlang的list其实跟scheme的list是一LQ甚臌定义的基本高阶函数都一Pmap,filterQappend{等,利用lists模块提供的filter和appendQ我们可以写出:<br> <div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #000000;">    qsort([])</span><span style="color: #000000;">-></span><span style="color: #000000;">[];  <br>    qsort([H</span><span style="color: #000000;">|</span><span style="color: #000000;">T])</span><span style="color: #000000;">-></span><span style="color: #000000;">  <br>        Lt</span><span style="color: #000000;">=</span><span style="color: #000000;">lists</span><span style="color: #000000;">:</span><span style="color: #000000;">filter(fun(E)</span><span style="color: #000000;">-></span><span style="color: #000000;">E</span><span style="color: #000000;"><</span><span style="color: #000000;">H end</span><span style="color: #000000;">,</span><span style="color: #000000;">T)</span><span style="color: #000000;">,</span><span style="color: #000000;">  <br>        St</span><span style="color: #000000;">=</span><span style="color: #000000;">lists</span><span style="color: #000000;">:</span><span style="color: #000000;">filter(fun(E)</span><span style="color: #000000;">-></span><span style="color: #000000;">E</span><span style="color: #000000;">>=</span><span style="color: #000000;">H end</span><span style="color: #000000;">,</span><span style="color: #000000;">T)</span><span style="color: #000000;">,</span><span style="color: #000000;">  <br>    lists</span><span style="color: #000000;">:</span><span style="color: #000000;">append(qsort(Lt)</span><span style="color: #000000;">,</span><span style="color: #000000;">lists</span><span style="color: #000000;">:</span><span style="color: #000000;">append([H]</span><span style="color: #000000;">,</span><span style="color: #000000;">qsort(St)))</span><span style="color: #000000;">.</span><span style="color: #000000;">  </span></div>     我们来比较下scheme和Erlang版本Q两者最显著的不同是Qscheme使用了条件语句ifQ而Erlang却是通过模式匚w来代替条件分支判断。同P在list的分解上面,Erlang也是利用了规则匹配来代替car,cdr函数Q从q里可以看出规则匚w在Erlang中的主要作用Q分解复杂数据结构以便赋值和条g分支的分z?br>    扯远些可以谈到模式匹配是?#8220;like-a”来代替消息分z֜传统命o式语a中严格的“is-a”Q这也跟现实世界的情冉|为符合,现实世界中我们对事物的判断都是模p。而这一点,不正?#8220;Duck-Typing”Q传l语a对于对象的类?type)判断来源于严格确定对象是什么类QclassQ,不是q个cd没有相应的ҎQ而事实上cMcdq两个概念ƈ不是一致的Q对象的cd更应该根据对象能够做什么来军_。扯q了Q这只是我读?a >p的链?/a>》得来的感受Q如果对模式匚wq有怀疑的话,让我们回到这个例子的Erlang版本Q代码中我们调用了两ơfilterq行全表扫描Q以便得到根据H切割的大两个部分,q在性能上有不小的媄响,那么我们能不能只q行一ơ全表扫描呢Q返回结果是“大小”两个部分Q看看Erlang应该怎么写:<br> <div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #0000ff;"></span><span style="color: #000000;"></span><span style="color: #000000;"></span><span style="color: #0000ff;">sort([]) -> [];<br>sort([Pivot|Rest]) -><br>   {Smaller, Bigger} = split(Pivot, Rest),<br>   lists:append(sort(Smaller), [Pivot|sort(Bigger)]). <br>split</span><span style="color: #000000;">(Pivot</span><span style="color: #000000;">,</span><span style="color: #000000;"> L) </span><span style="color: #000000;">-></span><span style="color: #000000;"><br></span><span style="color: #0000ff;">split</span><span style="color: #000000;">(Pivot</span><span style="color: #000000;">,</span><span style="color: #000000;"> L</span><span style="color: #000000;">,</span><span style="color: #000000;"> []</span><span style="color: #000000;">,</span><span style="color: #000000;"> [])</span><span style="color: #000000;">.</span><span style="color: #000000;"><br></span><span style="color: #0000ff;">split</span><span style="color: #000000;">(Pivot</span><span style="color: #000000;">,</span><span style="color: #000000;"> []</span><span style="color: #000000;">,</span><span style="color: #000000;"> Smaller</span><span style="color: #000000;">,</span><span style="color: #000000;"> Bigger) </span><span style="color: #000000;">-></span><span style="color: #000000;"><br>{Smaller</span><span style="color: #000000;">,</span><span style="color: #000000;">Bigger};<br></span><span style="color: #0000ff;">split</span><span style="color: #000000;">(Pivot</span><span style="color: #000000;">,</span><span style="color: #000000;"> [H</span><span style="color: #000000;">|</span><span style="color: #000000;">T]</span><span style="color: #000000;">,</span><span style="color: #000000;"> Smaller</span><span style="color: #000000;">,</span><span style="color: #000000;"> Bigger) when H </span><span style="color: #000000;"><</span><span style="color: #000000;"> Pivot </span><span style="color: #000000;">-></span><span style="color: #000000;"><br></span><span style="color: #0000ff;">split</span><span style="color: #000000;">(Pivot</span><span style="color: #000000;">,</span><span style="color: #000000;"> T</span><span style="color: #000000;">,</span><span style="color: #000000;"> [H</span><span style="color: #000000;">|</span><span style="color: #000000;">Smaller]</span><span style="color: #000000;">,</span><span style="color: #000000;"> Bigger);<br></span><span style="color: #0000ff;">split</span><span style="color: #000000;">(Pivot</span><span style="color: #000000;">,</span><span style="color: #000000;"> [H</span><span style="color: #000000;">|</span><span style="color: #000000;">T]</span><span style="color: #000000;">,</span><span style="color: #000000;"> Smaller</span><span style="color: #000000;">,</span><span style="color: #000000;"> Bigger) when H </span><span style="color: #000000;">>=</span><span style="color: #000000;"> Pivot </span><span style="color: #000000;">-></span><span style="color: #000000;"><br></span><span style="color: #0000ff;">split</span><span style="color: #000000;">(Pivot</span><span style="color: #000000;">,</span><span style="color: #000000;"> T</span><span style="color: #000000;">,</span><span style="color: #000000;"> Smaller</span><span style="color: #000000;">,</span><span style="color: #000000;"> [H</span><span style="color: #000000;">|</span><span style="color: #000000;">Bigger])</span><span style="color: #000000;">.</span></div> <br>    q几行代码充分展C模式匚w的威力,不过Erlang其实有内|的Ҏpartition用于切割list的,q里只是Z展现模式匚wQ因此上面的代码可以改ؓQ?br> <div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #0000ff;">sort</span><span style="color: #000000;">([]) </span><span style="color: #000000;">-></span><span style="color: #000000;"> [];<br></span><span style="color: #0000ff;">sort</span><span style="color: #000000;">([Pivot</span><span style="color: #000000;">|</span><span style="color: #000000;">Rest]) </span><span style="color: #000000;">-></span><span style="color: #000000;"><br>{Smaller</span><span style="color: #000000;">,</span><span style="color: #000000;"> Bigger} </span><span style="color: #000000;">=</span><span style="color: #000000;"> lists</span><span style="color: #000000;">:</span><span style="color: #000000;">partition(fun(E)</span><span style="color: #000000;">-></span><span style="color: #000000;">E</span><span style="color: #000000;"><</span><span style="color: #000000;">Pivot end</span><span style="color: #000000;">,</span><span style="color: #000000;"> Rest)</span><span style="color: #000000;">,</span><span style="color: #000000;"><br>lists</span><span style="color: #000000;">:</span><span style="color: #000000;">append(</span><span style="color: #0000ff;">sort</span><span style="color: #000000;">(Smaller)</span><span style="color: #000000;">,</span><span style="color: #000000;"> [Pivot</span><span style="color: #000000;">|</span><span style="color: #0000ff;">sort</span><span style="color: #000000;">(Bigger)])</span><span style="color: #000000;">.</span></div> <br>同样的代码改写ؓruby版本Q?br> <div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #000000;">def qsort(array)<br>  arr=array.dup<br>  </span><span style="color: #0000ff;">if</span><span style="color: #000000;"> arr</span><span style="color: #000000;">==</span><span style="color: #000000;">[]<br>    []<br>  </span><span style="color: #0000ff;">else</span><span style="color: #000000;"><br>    x</span><span style="color: #000000;">=</span><span style="color: #000000;">arr</span><span style="color: #000000;">.</span><span style="color: #0000ff;">shift</span><span style="color: #000000;"><br>    smaller</span><span style="color: #000000;">,</span><span style="color: #000000;">bigger</span><span style="color: #000000;">=</span><span style="color: #000000;">arr</span><span style="color: #000000;">.</span><span style="color: #000000;">partition{</span><span style="color: #000000;">|</span><span style="color: #000000;">e</span><span style="color: #000000;">|</span><span style="color: #000000;"> e</span><span style="color: #000000;"><=</span><span style="color: #000000;">x}<br>    qsort(smaller)</span><span style="color: #000000;">+</span><span style="color: #000000;">[x]</span><span style="color: #000000;">+</span><span style="color: #000000;">qsort(bigger)<br>  end<br>end</span></div>     ruby与Erlang都有q行赋|但是ruby不支持模式匹配。请注意rubyq没有尾递归优化Q因此上面的代码在数l比较大的时候会D栈溢出,想用ruby做函数式~程应该量多用@环和map,filter,collect{辅助高阶函数?br>    另外一个Erlang与ruby、scheme比较重要的区别是Erlang的变量只能赋gơ(或者说l定Q,也就是single assignment。这个特点与Erlang所要满的q行场景有紧密关p,当系l发生错误时Q就可以从原来的值重新启动Q务,而不用担心由于变量值的变化Dpȝ恢复困难?br><br><br><br><br><img src ="http://m.tkk7.com/killme2008/aggbug/130384.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://m.tkk7.com/killme2008/" target="_blank">dennis</a> 2007-07-15 16:11 <a href="http://m.tkk7.com/killme2008/archive/2007/07/15/130384.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Erlang分布式在linux和windows上的注意事项http://m.tkk7.com/killme2008/archive/2007/06/29/127099.htmldennisdennisFri, 29 Jun 2007 08:33:00 GMThttp://m.tkk7.com/killme2008/archive/2007/06/29/127099.htmlhttp://m.tkk7.com/killme2008/comments/127099.htmlhttp://m.tkk7.com/killme2008/archive/2007/06/29/127099.html#Feedback0http://m.tkk7.com/killme2008/comments/commentRss/127099.htmlhttp://m.tkk7.com/killme2008/services/trackbacks/127099.html
1.首先,分布式Erlang的实现提供了自有的安全机制来预防未经授权的Erlangpȝ讉K。Erlangpȝ与别的机器进行交互时必须有同Lmagic cookie,保存在一个称?erlang.cookie的文件中Qؓ了在两台不同机器间测试,需要编辑一?erlang.cookie,内容随便Q比如:
just_test

然后这份文件拷贝到windows环境变量HOMEPATH所在的目录 Q比如我的是C:\Documents and Settings\AdminQ而linux拯到环境变?HOME指向的目录,比如我这里是/root。特别注意一点,linux?erlang.cookie文g需要设|权限ؓ-r--------Q也是400Q仅所有者可读:
chmod 400 .erlang.cookie

2.因ؓErlang中的node名称是name@hostQhost是计机名,因此在两台机器上都需要将计算机名和ip加进hosts文gQ这个文件在linux下是?etc/hostsQ你可以用vi~辑如下Q?br>
127.0.0.1  localhost localhost
x.x.x.x    zane      zane
   #windows机器的ip和计机?/span>
Qhosts在windowspȝ的C:\WINDOWS\system32\drivers\etc目录下,~辑Q?br>
127.0.0.1       localhost
x.x.x.x   dennis 
#linux机器的名U和ip

3.W三步,要启动节点,通过命oerl -sname 或者erl -nameQ在此之前需要启动epmdq程Q它负责映射W号名到机器地址
在两个机器都执行Q?br>epmd -daemon

4.x配置完成Q可以测试下Erlang分布式编E在不同的机器和pȝ之间了(比如?a href="http://m.tkk7.com/killme2008/archive/2007/06/15/124547.html">Erlang入门(?--分布式编E?/a>》中的ping pong例子Q,very cool!



dennis 2007-06-29 16:33 发表评论
]]>
Erlang入门Q四Q——错误处理和鲁棒?/title><link>http://m.tkk7.com/killme2008/archive/2007/06/25/126156.html</link><dc:creator>dennis</dc:creator><author>dennis</author><pubDate>Mon, 25 Jun 2007 09:10:00 GMT</pubDate><guid>http://m.tkk7.com/killme2008/archive/2007/06/25/126156.html</guid><wfw:comment>http://m.tkk7.com/killme2008/comments/126156.html</wfw:comment><comments>http://m.tkk7.com/killme2008/archive/2007/06/25/126156.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://m.tkk7.com/killme2008/comments/commentRss/126156.html</wfw:commentRss><trackback:ping>http://m.tkk7.com/killme2008/services/trackbacks/126156.html</trackback:ping><description><![CDATA[     摘要:     M福州,事情没搞定,托给同学帮忙处理了,回家休息了两天就来上班了。回家这几天最大的收获是第四次重读《深入Java虚拟机》,以前不大明了的章节豁然开朗,有种开H的感觉Q水到渠成,看来技术的学习q是急不来?nbsp;   闲话不提QlErlang的学习,上次学习到分布式~程的章节,剩下三章分别是错误处理、构造健壮的pȝ和杂,错误处理?..  <a href='http://m.tkk7.com/killme2008/archive/2007/06/25/126156.html'>阅读全文</a><img src ="http://m.tkk7.com/killme2008/aggbug/126156.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://m.tkk7.com/killme2008/" target="_blank">dennis</a> 2007-06-25 17:10 <a href="http://m.tkk7.com/killme2008/archive/2007/06/25/126156.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Erlang入门Q三Q——分布式~程http://m.tkk7.com/killme2008/archive/2007/06/15/124547.htmldennisdennisFri, 15 Jun 2007 09:33:00 GMThttp://m.tkk7.com/killme2008/archive/2007/06/15/124547.htmlhttp://m.tkk7.com/killme2008/comments/124547.htmlhttp://m.tkk7.com/killme2008/archive/2007/06/15/124547.html#Feedback0http://m.tkk7.com/killme2008/comments/commentRss/124547.htmlhttp://m.tkk7.com/killme2008/services/trackbacks/124547.htmlErlang~程手册Q值的好好M遍?br />     所谓分布式的Erlang应用是运行在一pdErlang节点l成的网l之上。这Lpȝ的性质与单一节点上的Erlangpȝq没有什么不同。分布式q是?#8220;大词”QErlang从语a原生角度支持分布式编E,相比于java单不?br /> 一、分布式机制
下列的BIFs是用于分布式~程Q?br /> spawn(Node, Mod, Func, Args)
启动q程节点的一个进E?br />
spawn_link(Node, Mod, Func, Args)
启动q程节点的一个进Eƈ创徏q接到该q程

monitor_node(Node, Flag)
如果Flag是true,q个函数调用Q该函数Q的q程可以监控节点Node。如果节点已l舍弃或者ƈ不存在,调用的进E将收到一个{nodedown,Node}的消息。如果Flag是false,监控被关闭

node()
q回我们自己的进Ename

nodes()
q回其他已知的节点name列表

node(Item)
q回原来Item的节点名UͼItem可以是Pid,引用QreferenceQ或者端?port)

disconnect_node(Nodename)
从节点Nodename断开?br />
    节点是分布式Erlang的核心概c在一个分布式Erlang应用中,术语Qterm)节点(nodeQ意味着一个可以加入分布式transactions的运行系l。通过一个称为net kernal的特D进E,一个独立的Erlangpȝ可以成ؓ一个分布式Erlangpȝ的一部分。当net kernalq程启动的时候,我们U系l是alive的?br />
    与远E节点上的进E进行通信Q与同一节点内的q程通信只有一点不同:
  
   {Name, Node} ! Mess.
昄Q需要接收方增加一个参数Node用于指定接受q程所在的节点。节点的name一般是用@隔开的atomcdQ比如pong@dennisQ表C机名ؓdennis上的pong节点。通过执行:
erl -sname pong
在执行的计机中创Z个节点pong。ؓ了运行下面的例子Q你可能需要两台计机Q如果只有一収ͼ只要同时开两个Erlangpȝq以不同的节点名U运行也可以?br />
二、一些例子?br />     q个例子完全来自上面提到的翻译的q接Q关于分布式~程的章节。我增加了截囑֒说明?br /> 首先是代码:
-module(tut17).

-export([start_ping/1, start_pong/0,  ping/2, pong/0]).

ping(
0, Pong_Node) ->
    {pong
, Pong_Node} ! finished,
    io
:format("ping finished~n", []);

ping(N
, Pong_Node) ->
    {pong
, Pong_Node} ! {ping, self()},
    receive
        pong 
->
            io
:format("Ping received pong~n", [])
    end
,
    ping(N 
- 1, Pong_Node).

pong() 
->
    receive
        finished 
->
            io
:format("Pong finished~n", []);
        {ping
, Ping_PID} ->
            io
:format("Pong received ping~n", []),
            Ping_PID 
! pong,
            pong()
    end
.

start_pong() 
->
    register(pong
, spawn(tut17, pong, [])).

start_ping(Pong_Node) 
->
    spawn(tut17
, ping, [3, Pong_Node]).

    代码是创Z个相互通信的进E,怺发送消息ƈ通过io昄在屏q上Q本来是一个单一pȝ的例子,现在我们让两个进E运行在不同的两个节点上。注意start_pingҎQ创建的q程调用pingҎQpingҎ有两个参敎ͼ一个是发送消息的ơ数Q一个就是远E节点的name了,也就是我们将要创建的q程pong的所在节炏Vstart_pong创徏一个调用函数pong的进E,q注册ؓ名字pongQ因此在pingҎ中可以直接发送消息给pong)?br />     我是在windows机器上测试,首先打开两个cmdH口Qƈcd到Erlang的安装目录下的bin目录Q比如C:\Program Files\erl5.5.3\bin,上面的E序存ؓtut17.erlQƈ拯到同一个目录下。我们将创徏两个节点Q一个叫ping@dennis,一个叫pong@dennis,其中dennis是我的机器名。见下图Q?br />
采用同样的命?br />
erl -sname ping
创徏ping节点。然后在pong节点下执行start_pong()Q?br />

OK,q样在节点pong上启动了pongq程Q然后在ping节点调用start_pingQ传入参数就是pong@dennis
tut17:start_ping(pong@dennis).
执行l果如下图:

同样在pong节点上也可以看到Q?br />

    l果如我们预期的那样Q不同节点上的两个进E相互通信如此单。我们给模块tut17增加一个方法,用于启动q程q程Q也是调用spawn(Node,Module,Func,Args)ҎQ?br />
start(Ping_Node) ->
    register(pong
, spawn(tut17, pong, [])),
    spawn(Ping_Node
, tut17, ping, [3, node()]).
pongq程启动Ping_Node节点上的q程ping。具体结果不再给出?br />


    



dennis 2007-06-15 17:33 发表评论
]]>
Erlang入门Q二Q—ƈ发编E?/title><link>http://m.tkk7.com/killme2008/archive/2007/06/14/124355.html</link><dc:creator>dennis</dc:creator><author>dennis</author><pubDate>Thu, 14 Jun 2007 09:12:00 GMT</pubDate><guid>http://m.tkk7.com/killme2008/archive/2007/06/14/124355.html</guid><wfw:comment>http://m.tkk7.com/killme2008/comments/124355.html</wfw:comment><comments>http://m.tkk7.com/killme2008/archive/2007/06/14/124355.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://m.tkk7.com/killme2008/comments/commentRss/124355.html</wfw:commentRss><trackback:ping>http://m.tkk7.com/killme2008/services/trackbacks/124355.html</trackback:ping><description><![CDATA[    Erlang中的process——进E是轻量U的Qƈ且进E间无共享。查了很多资料,g没h说清楚轻量q程是什么概念,l箋查找中。。。闲话不提,q入q发~程的世界。本文算是学习笔讎ͼ也可以说是《Concurrent Programming in ERLANG》第五张的简略翻译? <br><span style="font-weight: bold;">1.q程的创?/span><br>    q程是一U自包含的、分隔的计算单元Qƈ与其他进Eƈ发运行在pȝ中,在进E间q没有一个承体p,当然Q应用开发者可以设计这样一个承体pR?br>    q程的创Z用如下语法:<br> <div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #000000;">Pid </span><span style="color: #000000;">=</span><span style="color: #000000;"> spawn(Module</span><span style="color: #000000;">,</span><span style="color: #000000;"> FunctionName</span><span style="color: #000000;">,</span><span style="color: #000000;"> ArgumentList)</span></div> <br>spawn接受三个参数Q模块名Q函数名以及参数列表Qƈq回一个代表创建的q程的标识符QPidQ?br>如果在一个已知进EPid1中执行:<br> <div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #000000;">Pid2 </span><span style="color: #000000;">=</span><span style="color: #000000;"> spawn(Mod</span><span style="color: #000000;">,</span><span style="color: #000000;"> Func</span><span style="color: #000000;">,</span><span style="color: #000000;"> Args)</span></div> 那么QPid2仅仅能被Pid1可见QErlangpȝ的安全性就构徏在限制进E扩展的基础上?br><br><span style="font-weight: bold;">2.q程间通信</span><br>    Erlangq程间的通信只能通过发送消息来实现Q消息的发送?W号Q?br> <div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #000000;">Pid </span><span style="color: #000000;">!</span><span style="color: #000000;"> Message</span></div>     其中Pid是接受消息的q程标记W,Message是消息。接受方和消息可以是M的有效的Erlangl构Q只要他们的l果q回的是q程标记W和消息?br>    消息的接受是使用receive关键字,语法如下Q?br> <div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #000000;">receive<br>      Message1 [when Guard1] </span><span style="color: #000000;">-></span><span style="color: #000000;"><br>          Actions1 ;<br>      Message2 [when Guard2] </span><span style="color: #000000;">-></span><span style="color: #000000;"><br>          Actions2 ;<br></span><span style="color: #000000;"><img src="http://m.tkk7.com/Images/dot.gif"></span><span style="color: #000000;"><br>end</span></div> <br>    每一个Erlangq程都有一?#8220;邮箱”Q所有发送到q程的消息都按照到达的顺序存储在“邮箱”里,上面所C的消息Message1,Message2Q当它们?#8220;邮箱”里的消息匚wQƈ且约束(GuardQ通过Q那么相应的ActionN执行,q且receiveq回的是ActionN的最后一条执行语句的l果。Erlang?#8220;邮箱”里的消息匚w是有选择性的Q只有匹配的消息被触发相应的ActionQ而没有匹配的消息仍然保留在“邮箱”里。这一机制保证了没有消息会d其他消息的到达?br>    消息到达的顺序ƈ不决定消息的优先U,q程轮检?#8220;邮箱”里的消息q行试匚w。消息的优先U别下文再讲?br><br>    如何接受特定q程的消息呢Q答案很单,发送方(sender)也附送在消息当中Q接收方通过模式匚w军_是否接受Q比如:<br> <div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #000000;">Pid </span><span style="color: #000000;">!</span><span style="color: #000000;"> {self()</span><span style="color: #000000;">,</span><span style="color: #000000;">abc}</span></div> l进EPid发送消息{self(),abc}Q利用selfq程得到发送方作ؓ消息发送。然后接收方Q?br> <div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #000000;">receive<br>  {Pid</span><span style="color: #000000;">1,</span><span style="color: #000000;">Msg} </span><span style="color: #000000;">-></span><span style="color: #000000;"><br></span><span style="color: #000000;"><img src="http://m.tkk7.com/Images/dot.gif"></span><span style="color: #000000;"><br>end</span></div> 通过模式匚w军_只有Pid1q程发送的消息才接受?br><br><span style="font-weight: bold;">3.一些例?/span><br>    仅说明下书中计数的进E例?我添加了单注释:<br> <div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #000000;">-</span><span style="color: #000000;">module(counter)</span><span style="color: #000000;">.</span><span style="color: #000000;"><br></span><span style="color: #000000;">-</span><span style="color: #000000;">compile(export_all)</span><span style="color: #000000;">.</span><span style="color: #000000;"><br></span><span style="color: #000000;">%</span><span style="color: #000000;"> start()Q返回一个新q程Q进E执行函数loop<br>start()</span><span style="color: #000000;">-></span><span style="color: #000000;">spawn(counter</span><span style="color: #000000;">,</span><span style="color: #000000;"> loop</span><span style="color: #000000;">,</span><span style="color: #000000;">[</span><span style="color: #800000;">0</span><span style="color: #000000;">])</span><span style="color: #000000;">.</span><span style="color: #000000;"><br></span><span style="color: #000000;">%</span><span style="color: #000000;"> 调用此操作递增计数<br>increment(Counter)</span><span style="color: #000000;">-></span><span style="color: #000000;"><br>    Counter</span><span style="color: #000000;">!</span><span style="color: #000000;">increament</span><span style="color: #000000;">.</span><span style="color: #000000;"><br></span><span style="color: #000000;">%</span><span style="color: #000000;"> q回当前计数?br>value(Counter)</span><span style="color: #000000;">-></span><span style="color: #000000;"><br>    Counter</span><span style="color: #000000;">!</span><span style="color: #000000;">{self()</span><span style="color: #000000;">,</span><span style="color: #000000;">value}</span><span style="color: #000000;">,</span><span style="color: #000000;"><br>    receive<br>        {Counter</span><span style="color: #000000;">,</span><span style="color: #000000;">Value}</span><span style="color: #000000;">-></span><span style="color: #000000;"><br>            </span><span style="color: #800080;">%q回l调用方</span><span style="color: #000000;"><br>            Value<br>        end</span><span style="color: #000000;">.</span><span style="color: #000000;"><br>  </span><span style="color: #800080;">%停止计数</span><span style="color: #000000;">      <br> stop(Counter)</span><span style="color: #000000;">-></span><span style="color: #000000;"><br>     Counter</span><span style="color: #000000;">!</span><span style="color: #000000;">{self()</span><span style="color: #000000;">,</span><span style="color: #000000;">stop}</span><span style="color: #000000;">.</span><span style="color: #000000;"><br> loop(Val)</span><span style="color: #000000;">-></span><span style="color: #000000;"><br>     receive<br>         </span><span style="color: #800080;">%接受不同的消?/span><span style="color: #000000;">Q决定返回结?br>         increament</span><span style="color: #000000;">-></span><span style="color: #000000;"><br>             loop(Val</span><span style="color: #000000;">+</span><span style="color: #800000;">1</span><span style="color: #000000;">);<br>         {From</span><span style="color: #000000;">,</span><span style="color: #000000;">value}</span><span style="color: #000000;">-></span><span style="color: #000000;"><br>             From</span><span style="color: #000000;">!</span><span style="color: #000000;">{self()</span><span style="color: #000000;">,</span><span style="color: #000000;">Val}</span><span style="color: #000000;">,</span><span style="color: #000000;"><br>             loop(Val);<br>         stop</span><span style="color: #000000;">-></span><span style="color: #000000;"><br>             true;<br>         </span><span style="color: #800080;">%不是以上3U消?/span><span style="color: #000000;">Q就l箋{待<br>         Other</span><span style="color: #000000;">-></span><span style="color: #000000;"><br>             loop(Val)<br>      end</span><span style="color: #000000;">.</span><span style="color: #000000;">   <br>             <br>                        <br>        <br><br></span></div> <br>调用方式Q?br> <div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #000000;"></span><span style="color: #000000;"></span><span style="color: #800000;">1</span><span style="color: #000000;">></span><span style="color: #000000;"> Counter1</span><span style="color: #000000;">=</span><span style="color: #000000;">counter</span><span style="color: #000000;">:</span><span style="color: #000000;">start()</span><span style="color: #000000;">.</span><span style="color: #000000;"><br></span><span style="color: #000000;"><</span><span style="color: #800000;">0.30</span><span style="color: #000000;">.</span><span style="color: #800000;">0</span><span style="color: #000000;">></span><span style="color: #000000;"><br></span><span style="color: #800000;">2</span><span style="color: #000000;">></span><span style="color: #000000;"> counter</span><span style="color: #000000;">:</span><span style="color: #000000;">value(Counter1)</span><span style="color: #000000;">.</span><span style="color: #000000;"><br></span><span style="color: #800000;">0</span><span style="color: #000000;"><br></span><span style="color: #800000;">3</span><span style="color: #000000;">></span><span style="color: #000000;"> counter</span><span style="color: #000000;">:</span><span style="color: #000000;">increment(Counter1)</span><span style="color: #000000;">.</span><span style="color: #000000;"><br>increament<br></span><span style="color: #800000;">4</span><span style="color: #000000;">></span><span style="color: #000000;"> counter</span><span style="color: #000000;">:</span><span style="color: #000000;">value(Counter1)</span><span style="color: #000000;">.</span><span style="color: #000000;"><br></span><span style="color: #800000;">1</span><span style="color: #000000;"><br></span></div> <br>Zq程的消息传递机制可以很Ҏ地实现有限状态机QFSMQ,状态用函数表C,而事件就是消息。具体不再展开<br><br><span style="font-weight: bold;">4.时讄</span><br>    Erlang中的receive语法可以d一个额外选项QtimeoutQ类|<br> <div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #000000;">receive<br>   Message1 [when Guard1] </span><span style="color: #000000;">-></span><span style="color: #000000;"><br>     Actions1 ;<br>   Message2 [when Guard2] </span><span style="color: #000000;">-></span><span style="color: #000000;"><br>     Actions2 ;<br>   </span><span style="color: #000000;"><img src="http://m.tkk7.com/Images/dot.gif"></span><span style="color: #000000;"><br>   after<br>      TimeOutExpr </span><span style="color: #000000;">-></span><span style="color: #000000;"><br>         ActionsT<br>end</span></div> <br>after之后的TimeOutExpr表达式返回一个整数timeQ毫U别)Q时间的_E度依赖于Erlang在操作系l或者硬件的实现。如果在time毫秒内,没有一个消息被选中Q超时设|将生效Q也是ActionT执行。time有两个特D|<br>1)<span style="font-weight: bold;">infinity</span>(无穷?Qinfinity是一个atomQ指定了时讄永q不会被执行?br>2) <span style="font-weight: bold;">0</span>Q超时如果设定ؓ0意味着时讄立L行,但是pȝ首先尝试当?#8220;邮箱”里的消息?br><br>    时的常见几个应用,比如挂v当前q程多少毫秒Q?br> <div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #0000ff;">sleep</span><span style="color: #000000;">(</span><span style="color: #0000ff;">Time</span><span style="color: #000000;">) </span><span style="color: #000000;">-></span><span style="color: #000000;"><br>  receive<br>    after </span><span style="color: #0000ff;">Time</span><span style="color: #000000;"> </span><span style="color: #000000;">-></span><span style="color: #000000;"><br>    true<br>end</span><span style="color: #000000;">.</span></div>     比如清空q程?#8220;邮箱”,丢弃“邮箱”里的所有消息:<br>    <div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #000000;">flush_buffer() </span><span style="color: #000000;">-></span><span style="color: #000000;"><br>  receive<br>    AnyMessage </span><span style="color: #000000;">-></span><span style="color: #000000;"><br>      flush_buffer()<br>  after </span><span style="color: #800000;">0</span><span style="color: #000000;"> </span><span style="color: #000000;">-></span><span style="color: #000000;"><br>    true<br>end</span><span style="color: #000000;">.</span></div>     当前进E永q挂P<br> <div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #000000;">  suspend() </span><span style="color: #000000;">-></span><span style="color: #000000;"><br>    receive<br>    after<br>        infinity </span><span style="color: #000000;">-></span><span style="color: #000000;"><br>            true<br>    end</span><span style="color: #000000;">.</span></div>     时也可以应用于实现定时器,比如下面q个例子Q创Z个进E,q个q程在讑֮旉后向自己发送消息:<br> <div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #000000;">-</span><span style="color: #000000;">module(timer)</span><span style="color: #000000;">.</span><span style="color: #000000;"><br></span><span style="color: #000000;">-</span><span style="color: #000000;">export([timeout</span><span style="color: #000000;">/</span><span style="color: #800000;">2</span><span style="color: #000000;">,</span><span style="color: #000000;">cancel</span><span style="color: #000000;">/</span><span style="color: #800000;">1</span><span style="color: #000000;">,</span><span style="color: #000000;">timer</span><span style="color: #000000;">/</span><span style="color: #800000;">3</span><span style="color: #000000;">])</span><span style="color: #000000;">.</span><span style="color: #000000;"><br>timeout(</span><span style="color: #0000ff;">Time</span><span style="color: #000000;">,</span><span style="color: #000000;"> </span><span style="color: #0000ff;">Alarm</span><span style="color: #000000;">) </span><span style="color: #000000;">-></span><span style="color: #000000;"><br>   spawn(timer</span><span style="color: #000000;">,</span><span style="color: #000000;"> timer</span><span style="color: #000000;">,</span><span style="color: #000000;"> [self()</span><span style="color: #000000;">,</span><span style="color: #0000ff;">Time</span><span style="color: #000000;">,</span><span style="color: #0000ff;">Alarm</span><span style="color: #000000;">])</span><span style="color: #000000;">.</span><span style="color: #000000;"><br>cancel(Timer) </span><span style="color: #000000;">-></span><span style="color: #000000;"><br>   Timer </span><span style="color: #000000;">!</span><span style="color: #000000;"> {self()</span><span style="color: #000000;">,</span><span style="color: #000000;">cancel}</span><span style="color: #000000;">.</span><span style="color: #000000;"><br>timer(Pid</span><span style="color: #000000;">,</span><span style="color: #000000;"> </span><span style="color: #0000ff;">Time</span><span style="color: #000000;">,</span><span style="color: #000000;"> </span><span style="color: #0000ff;">Alarm</span><span style="color: #000000;">) </span><span style="color: #000000;">-></span><span style="color: #000000;"><br>   receive<br>    {Pid</span><span style="color: #000000;">,</span><span style="color: #000000;">cancel} </span><span style="color: #000000;">-></span><span style="color: #000000;"><br>       true<br>   after </span><span style="color: #0000ff;">Time</span><span style="color: #000000;"> </span><span style="color: #000000;">-></span><span style="color: #000000;"><br>       Pid </span><span style="color: #000000;">!</span><span style="color: #000000;"> </span><span style="color: #0000ff;">Alarm</span><span style="color: #000000;"><br>end</span><span style="color: #000000;">.</span></div> <br>    <br><span style="font-weight: bold;">5、注册进E?/span><br>    Zl进E发送消息,我们需要知道进E的PidQ但是在某些情况下:在一个很大系l里面有很多的全局serversQ或者ؓ了安全考虑需要隐藏进EPid。ؓ了达到可以发送消息给一个不知道Pid的进E的目的Q我们提供了注册q程的办法,l进E们注册名字Q这些名字必Latom?br>    基本的调用Ş式:<br> <div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #000000; font-weight: bold;">register(Name,</span><span style="color: #000000;"><span style="font-weight: bold;"> Pid)</span><br>Name与进EPid联系h<br><br><span style="font-weight: bold;">unregister(Name)</span><br>取消Name与相应进E的对应关系?br><br><span style="font-weight: bold;">whereis(Name)</span><br>q回Name所兌的进E的PidQ如果没有进E与之关联,p回atom</span><span style="color: #000000;">:</span><span style="color: #000000;">undefined<br><br><span style="font-weight: bold;">registered()</span><br>q回当前注册的进E的名字列表</span></div> <br><span style="font-weight: bold;">6.q程的优先</span><br>讑֮q程的优先可以使用BIFs:<br><span style="font-weight: bold;">process_flag(priority, Pri)</span> <br><br>Pri可以是normal、low,默认都是normal<br>优先U高的进E将相对低的执行多一炏V?br><br><span style="font-weight: bold;">7.q程l(process group)</span><br>    所有的ERLANGq程都有一个Pid与一个他们共有的UCؓGroup Leader相关联,当一个新的进E被创徏的时候将被加入同一个进E组。最初的pȝq程的Group Leader是它自w,因此它也是所有被创徏q程及子q程的Group Leader。这意味着Erlang的进E被l织ZTreeQ其中的根节点就是第一个被创徏的进E。下面的BIFs被用于操U进E组Q?br><span style="font-weight: bold;">group_leader()</span><br>q回执行q程的Group Leader的Pid<br><span style="font-weight: bold;">group_leader(Leader, Pid)</span><br>讄q程Pid的Group LeaderE的Leader <br><br><span style="font-weight: bold;">8.</span>Erlang的进E模型很ҎL建Client-Server的模型,书中有一节专门讨Zq一点,着重强调了接口的设计以及抽象层ơ的隔离问题Q不译了?br><br> <img src ="http://m.tkk7.com/killme2008/aggbug/124355.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://m.tkk7.com/killme2008/" target="_blank">dennis</a> 2007-06-14 17:12 <a href="http://m.tkk7.com/killme2008/archive/2007/06/14/124355.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>ErlangԌ译Q?/title><link>http://m.tkk7.com/killme2008/archive/2007/06/14/124226.html</link><dc:creator>dennis</dc:creator><author>dennis</author><pubDate>Thu, 14 Jun 2007 01:28:00 GMT</pubDate><guid>http://m.tkk7.com/killme2008/archive/2007/06/14/124226.html</guid><wfw:comment>http://m.tkk7.com/killme2008/comments/124226.html</wfw:comment><comments>http://m.tkk7.com/killme2008/archive/2007/06/14/124226.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://m.tkk7.com/killme2008/comments/commentRss/124226.html</wfw:commentRss><trackback:ping>http://m.tkk7.com/killme2008/services/trackbacks/124226.html</trackback:ping><description><![CDATA[<img alt="Erlang logo" src="http://m.tkk7.com/killme2008/admin/erlang_small.gif" align="right" border="0"> <h1>Erlang前世今生</h1> <hr> <h1>1982 - 1985</h1> 我们使用?> 20U语aq行了电信行业的~程实验Q结论是Q这L语言需要是一门高度的抽象的语a才能辑ֈ生力目标?l我们留下印象的有:List,Prolog,Parlog ...) <h1>1985 - 86</h1> 我们使用Lisp,Prolog,Parlog{语aq行了实验,l论是:q样的语a需要原生支持的q发控制和容错处理,q且执行模型必须没有使用回溯。(排除了List和Prolog.) 而且它必L有ƈ发粒度比如一个异步的电话q程可以用语a的一个进E表C(排除了ParlogQ。最后我们不得不开发一门我们自q语言Q它拥有 Lisp,Prolog和Parlog的特性,但内|了q发和容错处理? <h1>1987</h1> W一ơ用erlangq行实验? <h1>1988</h1> ACS/DunderQ项?W一阶段Q外来用户用erlangq行PABX(专用自动交换分机)功能的原型构建, <em>Erlang走出了实验室Q?/em> <h1>1989</h1> <p> ACS/DunderQ项?W二阶段Q重新改造了完整的MD-110pȝ?/10Q结?相比于用PLEX的构建有>>10倍的效率提高Q? </p> <h1>1990</h1>  Erlang正式以ISS'90标准发布Q这带来不少的新用户Q比如Bellcore? <h1>1991</h1> Erlang发布了更快的版本实现l用PErlang应用于电?91Q项目?Q,更多功能比如~译器、图形接口等? <h1>1992</h1>  更多的新用户Q许多高速发展的目。Erlang可以q行于VxWorks,PC,Macintosh{系l。有三个应用使用了ISS'92标准的Erlang? <h1>1993</h1>  分布式支持加q了Erlang,q得erlang可以q行一个自发系l在不同的硬件上。决定向外部发布Erlang的实玎ͼ从爱立信分离出独立的部门开始维护和支持Erlang的实现和Erlang工具的开发工作? <br><img src ="http://m.tkk7.com/killme2008/aggbug/124226.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://m.tkk7.com/killme2008/" target="_blank">dennis</a> 2007-06-14 09:28 <a href="http://m.tkk7.com/killme2008/archive/2007/06/14/124226.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Erlang入门Q一Q?/title><link>http://m.tkk7.com/killme2008/archive/2007/06/13/123860.html</link><dc:creator>dennis</dc:creator><author>dennis</author><pubDate>Wed, 13 Jun 2007 06:36:00 GMT</pubDate><guid>http://m.tkk7.com/killme2008/archive/2007/06/13/123860.html</guid><wfw:comment>http://m.tkk7.com/killme2008/comments/123860.html</wfw:comment><comments>http://m.tkk7.com/killme2008/archive/2007/06/13/123860.html#Feedback</comments><slash:comments>4</slash:comments><wfw:commentRss>http://m.tkk7.com/killme2008/comments/commentRss/123860.html</wfw:commentRss><trackback:ping>http://m.tkk7.com/killme2008/services/trackbacks/123860.html</trackback:ping><description><![CDATA[    读erlang.org上面的Erlang Course四天教程<br><span style="font-weight: bold;">1.</span>数字cdQ需要注意两?br>1QB#Val表示以Bq制存储的数字ValQ比?br> <div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #800000;">7</span><span style="color: #000000;">></span><span style="color: #000000;"> </span><span style="color: #800000;">2</span><span style="color: #008000;">#</span><span style="color: #008000;">101.</span><span style="color: #008000;"><br></span><span style="color: #800000;">5</span><span style="color: #000000;"><br></span></div> <span style="font-weight: bold;">?/span>q制存储?01是10q制??br>2Q?Char表示字符Char的ascii~码Q比?A表示65<br><br><span style="font-weight: bold;">2.</span>比较难以译的概念——atomQ可以理解成帔RQ它可以包含M字符Q以写字母开_如果不是以小写字母开头或者是字母之外的符P需要用单引号包括v来,比如abc,'AB'<br><br><span style="font-weight: bold;">3.</span>另一个概念——Tuple,有h译成元l,可以理解成定长数l,是Erlang的基数据l构之一Q?br> <div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #800000;">8</span><span style="color: #000000;">></span><span style="color: #000000;"> {</span><span style="color: #800000;">1</span><span style="color: #000000;">,</span><span style="color: #800000;">2</span><span style="color: #000000;">,</span><span style="color: #800000;">3</span><span style="color: #000000;">,</span><span style="color: #800000;">4</span><span style="color: #000000;">,</span><span style="color: #800000;">5</span><span style="color: #000000;">}</span><span style="color: #000000;">.</span><span style="color: #000000;"><br>{</span><span style="color: #800000;">1</span><span style="color: #000000;">,</span><span style="color: #800000;">2</span><span style="color: #000000;">,</span><span style="color: #800000;">3</span><span style="color: #000000;">,</span><span style="color: #800000;">4</span><span style="color: #000000;">,</span><span style="color: #800000;">5</span><span style="color: #000000;">}<br></span><span style="color: #800000;">9</span><span style="color: #000000;">></span><span style="color: #000000;"> {a</span><span style="color: #000000;">,</span><span style="color: #000000;">b</span><span style="color: #000000;">,</span><span style="color: #000000;">c</span><span style="color: #000000;">,</span><span style="color: #800000;">1</span><span style="color: #000000;">,</span><span style="color: #800000;">2</span><span style="color: #000000;">}</span><span style="color: #000000;">.</span><span style="color: #000000;"><br>{a</span><span style="color: #000000;">,</span><span style="color: #000000;">b</span><span style="color: #000000;">,</span><span style="color: #000000;">c</span><span style="color: #000000;">,</span><span style="color: #800000;">1</span><span style="color: #000000;">,</span><span style="color: #800000;">2</span><span style="color: #000000;">}<br></span><span style="color: #800000;">10</span><span style="color: #000000;">></span><span style="color: #000000;"> size({</span><span style="color: #800000;">1</span><span style="color: #000000;">,</span><span style="color: #800000;">2</span><span style="color: #000000;">,</span><span style="color: #800000;">3</span><span style="color: #000000;">,</span><span style="color: #000000;">a</span><span style="color: #000000;">,</span><span style="color: #000000;">b</span><span style="color: #000000;">,</span><span style="color: #000000;">c})</span><span style="color: #000000;">.</span><span style="color: #000000;"><br></span><span style="color: #800000;">6</span><span style="color: #000000;"><br></span></div> 内置函数size求长度,元组可以嵌套元组或者其他结构。下面所讲的列表也一栗?br><br><span style="font-weight: bold;">4.</span>另外一个基数据l构是各个语言都有的listQ列表)Q在[]内以,隔开Q可以动态改变大, <div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #000000;">    [</span><span style="color: #800000;">123</span><span style="color: #000000;">,</span><span style="color: #000000;"> xyz]<br>    [</span><span style="color: #800000;">123</span><span style="color: #000000;">,</span><span style="color: #000000;"> def</span><span style="color: #000000;">,</span><span style="color: #000000;"> abc]<br>    [{person</span><span style="color: #000000;">,</span><span style="color: #000000;"> </span><span style="color: #000000; font-weight: bold;">'</span><span style="color: #000000; font-weight: bold;">Joe</span><span style="color: #000000; font-weight: bold;">'</span><span style="color: #000000;">,</span><span style="color: #000000;"> </span><span style="color: #000000; font-weight: bold;">'</span><span style="color: #000000; font-weight: bold;">Armstrong</span><span style="color: #000000; font-weight: bold;">'</span><span style="color: #000000;">}</span><span style="color: #000000;">,</span><span style="color: #000000;"><br>        {person</span><span style="color: #000000;">,</span><span style="color: #000000;"> </span><span style="color: #000000; font-weight: bold;">'</span><span style="color: #000000; font-weight: bold;">Robert</span><span style="color: #000000; font-weight: bold;">'</span><span style="color: #000000;">,</span><span style="color: #000000;"> </span><span style="color: #000000; font-weight: bold;">'</span><span style="color: #000000; font-weight: bold;">Virding</span><span style="color: #000000; font-weight: bold;">'</span><span style="color: #000000;">}</span><span style="color: #000000;">,</span><span style="color: #000000;"><br>        {person</span><span style="color: #000000;">,</span><span style="color: #000000;"> </span><span style="color: #000000; font-weight: bold;">'</span><span style="color: #000000; font-weight: bold;">Mike</span><span style="color: #000000; font-weight: bold;">'</span><span style="color: #000000;">,</span><span style="color: #000000;"> </span><span style="color: #000000; font-weight: bold;">'</span><span style="color: #000000; font-weight: bold;">Williams</span><span style="color: #000000; font-weight: bold;">'</span><span style="color: #000000;">}<br>    ]</span></div> 可以使用内置函数length求列表大。以""包含的ascii字母代表一个列表,里面的元素就是这些字母的ascii|比如"abc"表示列表[97,98,99]?br><br><span style="font-weight: bold;">5.</span>通过q两个数据结构可以组合成各种复杂l构Q与Lisp的cons、list演化出各U结构一L奇妙,Erlang也可以当作是操作列表的语a?br><br><span style="font-weight: bold;">6.</span>Erlang中变量有两个特点Q?br>1Q变量必M大写字母或者下划线开_可以包含字母、下划线和@<br>2Q变量只能绑定一ơ,也就是所谓的Single Assignment。或者以一般的说法是只能赋gơ,其实Erlangq没有赋DL概念,=号也是用于验证匹配?br><br><span style="font-weight: bold;">7.</span>模式匚w——Pattern MatchingQErlang的模式匹配非常强大,看了<strong>buaawhl</strong>的?a >Erlang语法提要</a>》的介绍Q模式匹配的功能不仅仅在评中介l的数据l构的拆解,在程序的分派也扮演重要角Ԍ或者说Erlang的控制的{是通过模式匚w来实现的。具体功能参见链接,l出书中拆解列表的例子:<br> <div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #000000;">    [A</span><span style="color: #000000;">,</span><span style="color: #000000;">B</span><span style="color: #000000;">|</span><span style="color: #000000;">C] </span><span style="color: #000000;">=</span><span style="color: #000000;"> [</span><span style="color: #800000;">1</span><span style="color: #000000;">,</span><span style="color: #800000;">2</span><span style="color: #000000;">,</span><span style="color: #800000;">3</span><span style="color: #000000;">,</span><span style="color: #800000;">4</span><span style="color: #000000;">,</span><span style="color: #800000;">5</span><span style="color: #000000;">,</span><span style="color: #800000;">6</span><span style="color: #000000;">,</span><span style="color: #800000;">7</span><span style="color: #000000;">]<br>        Succeeds </span><span style="color: #000000;">-</span><span style="color: #000000;"> binds A </span><span style="color: #000000;">=</span><span style="color: #000000;"> </span><span style="color: #800000;">1</span><span style="color: #000000;">,</span><span style="color: #000000;"> B </span><span style="color: #000000;">=</span><span style="color: #000000;"> </span><span style="color: #800000;">2</span><span style="color: #000000;">,</span><span style="color: #000000;"><br>        C </span><span style="color: #000000;">=</span><span style="color: #000000;"> [</span><span style="color: #800000;">3</span><span style="color: #000000;">,</span><span style="color: #800000;">4</span><span style="color: #000000;">,</span><span style="color: #800000;">5</span><span style="color: #000000;">,</span><span style="color: #800000;">6</span><span style="color: #000000;">,</span><span style="color: #800000;">7</span><span style="color: #000000;">]<br>    <br>    [H</span><span style="color: #000000;">|</span><span style="color: #000000;">T] </span><span style="color: #000000;">=</span><span style="color: #000000;"> [</span><span style="color: #800000;">1</span><span style="color: #000000;">,</span><span style="color: #800000;">2</span><span style="color: #000000;">,</span><span style="color: #800000;">3</span><span style="color: #000000;">,</span><span style="color: #800000;">4</span><span style="color: #000000;">]<br>        Succeeds </span><span style="color: #000000;">-</span><span style="color: #000000;"> binds H </span><span style="color: #000000;">=</span><span style="color: #000000;"> </span><span style="color: #800000;">1</span><span style="color: #000000;">,</span><span style="color: #000000;"> T </span><span style="color: #000000;">=</span><span style="color: #000000;"> [</span><span style="color: #800000;">2</span><span style="color: #000000;">,</span><span style="color: #800000;">3</span><span style="color: #000000;">,</span><span style="color: #800000;">4</span><span style="color: #000000;">]<br>    <br>    [H</span><span style="color: #000000;">|</span><span style="color: #000000;">T] </span><span style="color: #000000;">=</span><span style="color: #000000;"> [abc]<br>        Succeeds </span><span style="color: #000000;">-</span><span style="color: #000000;"> binds H </span><span style="color: #000000;">=</span><span style="color: #000000;"> abc</span><span style="color: #000000;">,</span><span style="color: #000000;"> T </span><span style="color: #000000;">=</span><span style="color: #000000;"> []<br>    <br>    [H</span><span style="color: #000000;">|</span><span style="color: #000000;">T] </span><span style="color: #000000;">=</span><span style="color: #000000;"> []<br>        Fails</span></div> <br>下面会给出更多模式匹配的例子Q给Z个模块用来计列表等<br><br><span style="font-weight: bold;">8.</span>Erlang中函数的定义必须在一个模块内QModuleQ,q且模块和函数的名称都必LatomQ函数的参数可以是Q何的Erlangcd或者数据结构,函数要被调用需要从模块中导出,函数调用的Ş式类|<br>moduleName:funcName(Arg1,Arg2,...).<br>写我们的W一个ErlangE序Qh见hqHello WorldQ?br> <div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #000000;">-</span><span style="color: #000000;">module(helloWorld)</span><span style="color: #000000;">.</span><span style="color: #000000;"><br></span><span style="color: #000000;">-</span><span style="color: #000000;">export([run</span><span style="color: #000000;">/</span><span style="color: #800000;">1</span><span style="color: #000000;">])</span><span style="color: #000000;">.</span><span style="color: #000000;"><br>run(Name)</span><span style="color: #000000;">-></span><span style="color: #000000;"><br>    io</span><span style="color: #000000;">:</span><span style="color: #0000ff;">format</span><span style="color: #000000;">(</span><span style="color: #000000; font-weight: bold;">"</span><span style="color: #000000; font-weight: bold;">Hello World ~w~n</span><span style="color: #000000; font-weight: bold;">"</span><span style="color: #000000;">,</span><span style="color: #000000;">[Name])</span><span style="color: #000000;">.</span></div> 存ؓhelloWorld.erlQ在Erlang Shell中执行:<br> <div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #800000;">2</span><span style="color: #000000;">></span><span style="color: #000000;"> c(helloWorld)</span><span style="color: #000000;">.</span><span style="color: #000000;"><br>{ok</span><span style="color: #000000;">,</span><span style="color: #000000;">helloWorld}<br></span><span style="color: #800000;">3</span><span style="color: #000000;">></span><span style="color: #000000;"> helloWorld</span><span style="color: #000000;">:</span><span style="color: #000000;">run(dennis)</span><span style="color: #000000;">.</span><span style="color: #000000;"><br><span style="font-weight: bold;">Hello World dennis</span><br>ok<br></span></div> 打印出来了,现在解释下程序构造,<br> <div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #000000;">-</span><span style="color: #000000;">module(helloWorld)</span><span style="color: #000000;">.</span><span style="color: #000000;"><br></span></div> q一行声明了模块helloWorldQ函数必d义在模块内,q且模块名称必须与源文g名相同?br> <div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #000000;">-</span><span style="color: #000000;">export([run</span><span style="color: #000000;">/</span><span style="color: #800000;">1</span><span style="color: #000000;">])</span><span style="color: #000000;">.</span></div> 而这一行声明导出的函数Qrun/1指的是有一个参数的run函数Q因为Erlang允许定义同名的有不同参数的多个函敎ͼ通过指定/1来说明要导出的是哪个函数?br>接下来就是函数定义了Q?br> <div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #000000;">run(Name)</span><span style="color: #000000;">-></span><span style="color: #000000;"><br>    io</span><span style="color: #000000;">:</span><span style="color: #0000ff;">format</span><span style="color: #000000;">(</span><span style="color: #000000; font-weight: bold;">"</span><span style="color: #000000; font-weight: bold;">Hello World ~w~n</span><span style="color: #000000; font-weight: bold;">"</span><span style="color: #000000;">,</span><span style="color: #000000;">[Name])</span><span style="color: #000000;">.</span></div> 大写开头的是变量NameQ调用io模块的formatҎ输出Q~w可以理解成占位符Q将被实际Name取代Q~n是换行了。注意,函数定义完了要以句号.l束。然后执行c(helloWorld).~译源代码,执行Q?br> <div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #000000;">helloWorld</span><span style="color: #000000;">:</span><span style="color: #000000;">run(dennis);</span></div> <br><span style="font-weight: bold;">9.</span>内置的常用函敎ͼ<br> <div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #000000;">    date()<br>    </span><span style="color: #0000ff;">time</span><span style="color: #000000;">()<br>    </span><span style="color: #0000ff;">length</span><span style="color: #000000;">([</span><span style="color: #800000;">1</span><span style="color: #000000;">,</span><span style="color: #800000;">2</span><span style="color: #000000;">,</span><span style="color: #800000;">3</span><span style="color: #000000;">,</span><span style="color: #800000;">4</span><span style="color: #000000;">,</span><span style="color: #800000;">5</span><span style="color: #000000;">])<br>    size({a</span><span style="color: #000000;">,</span><span style="color: #000000;">b</span><span style="color: #000000;">,</span><span style="color: #000000;">c})<br>    atom_to_list(an_atom)<br>    list_to_tuple([</span><span style="color: #800000;">1</span><span style="color: #000000;">,</span><span style="color: #800000;">2</span><span style="color: #000000;">,</span><span style="color: #800000;">3</span><span style="color: #000000;">,</span><span style="color: #800000;">4</span><span style="color: #000000;">])<br>    integer_to_list(</span><span style="color: #800000;">2234</span><span style="color: #000000;">)<br>    tuple_to_list({})<br>    hd([1,2,3,4])  %输出1Q也是列表的headQ类似Lisp的car<br>    tl([1,2,3,4])  %输出[2,3,4],也就是列表的tail,cMList的cdr<br></span></div> <br><span style="font-weight: bold;">10.</span>常见Shell命oQ?br>1Q?span style="font-weight: bold;">h().</span> 用来打印最q的20条历史命?br>2Q?span style="font-weight: bold;">b().</span> 查看所有绑定的变量<br>3) <span style="font-weight: bold;">f().</span> 取消Q遗忘)所有绑定的变量?br>4) <span style="font-weight: bold;">f(Val).</span>  取消指定的绑定变?br>5) <span style="font-weight: bold;">e(n).</span>   执行Wn条历史命?br>6) <span style="font-weight: bold;">e(-1).</span>  执行上一条shell命o<br><br><span style="font-weight: bold;">11.</span>又一个不知道怎么译的概念——Guard。翻译成U束Q呵c用于限制变量的cd和范_比如Q?br> <div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #000000;">     number(X)    </span><span style="color: #000000;">-</span><span style="color: #000000;"> X 是数?br>    integer(X)    </span><span style="color: #000000;">-</span><span style="color: #000000;"> X 是整?br>    float(X)    </span><span style="color: #000000;">-</span><span style="color: #000000;"> X 是QҎ<br>    atom(X)        </span><span style="color: #000000;">-</span><span style="color: #000000;"> X 是一个atom<br>    tuple(X)    </span><span style="color: #000000;">-</span><span style="color: #000000;"> X 是一个元l?br>    list(X)        </span><span style="color: #000000;">-</span><span style="color: #000000;"> X 是一个列?br>    <br>    </span><span style="color: #0000ff;">length</span><span style="color: #000000;">(X) </span><span style="color: #000000;">==</span><span style="color: #000000;"> </span><span style="color: #800000;">3</span><span style="color: #000000;">    </span><span style="color: #000000;">-</span><span style="color: #000000;"> X 是一个长度ؓ3的列?br>    size(X) </span><span style="color: #000000;">==</span><span style="color: #000000;"> </span><span style="color: #800000;">2</span><span style="color: #000000;">    </span><span style="color: #000000;">-</span><span style="color: #000000;"> X 是一个长度ؓ2的元l?br>    <br>    X </span><span style="color: #000000;">></span><span style="color: #000000;"> Y </span><span style="color: #000000;">+</span><span style="color: #000000;"> Z    </span><span style="color: #000000;">-</span><span style="color: #000000;"> X </span><span style="color: #000000;">></span><span style="color: #000000;">Y</span><span style="color: #000000;">+</span><span style="color: #000000;">Z<br>    X </span><span style="color: #000000;">==</span><span style="color: #000000;"> Y        </span><span style="color: #000000;">-</span><span style="color: #000000;"> X 与Y相等<br>    X </span><span style="color: #000000;">=:=</span><span style="color: #000000;"> Y        </span><span style="color: #000000;">-</span><span style="color: #000000;"> X 全等于Y<br>    (比如Q?nbsp;</span><span style="color: #800000;">1</span><span style="color: #000000;"> </span><span style="color: #000000;">==</span><span style="color: #000000;"> </span><span style="color: #800000;">1.0</span><span style="color: #000000;"> 成功<br>               </span><span style="color: #800000;">1</span><span style="color: #000000;"> </span><span style="color: #000000;">=:=</span><span style="color: #000000;"> </span><span style="color: #800000;">1.0</span><span style="color: #000000;"> p|)</span></div> Z方便比较QErlang规定如下的比较顺序:<br> <div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #000000;">number </span><span style="color: #000000;"><</span><span style="color: #000000;"> atom </span><span style="color: #000000;"><</span><span style="color: #000000;"> reference </span><span style="color: #000000;"><</span><span style="color: #000000;"> port </span><span style="color: #000000;"><</span><span style="color: #000000;"> pid </span><span style="color: #000000;"><</span><span style="color: #000000;"> tuple </span><span style="color: #000000;"><</span><span style="color: #000000;"> list</span></div> 其中pid是process的id?br><br><span style="font-weight: bold;">12.</span>忘了介绍apply函数Q这个函数对于熟悉javascript的h来说很亲切,javascript实现mixin得靠它Q它的调用方式如下:<br> <pre>apply(Mod, Func, Args),三个参数分别是模块、函C及参数列表,比如调用我们的第一个ErlangE序Q?br> <div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #000000;">apply(helloWorld</span><span style="color: #000000;">,</span><span style="color: #000000;">run</span><span style="color: #000000;">,</span><span style="color: #000000;">[dennis])</span><span style="color: #000000;">.</span></div> <span style="font-weight: bold;">13.</span>if和case语句Qif语句的结构如下:<br>if<br> Guard1 -><br> Sequence1 ;<br> Guard2 -><br> Sequence2 ;<br>...<br>end<br>而case语句的结构如下:<br> <div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #000000;">case Expr of<br> Pattern1 [when Guard1] </span><span style="color: #000000;">-></span><span style="color: #000000;"> Seq1;<br> Pattern2 [when Guard2] </span><span style="color: #000000;">-></span><span style="color: #000000;"> Seq2;<br></span><span style="color: #000000;"><img src="http://m.tkk7.com/Images/dot.gif"></span><span style="color: #000000;"><br> PatternN [when GuardN] </span><span style="color: #000000;">-></span><span style="color: #000000;"> SeqN<br>end</span><br> <br></div> </pre> if和case语句都有一个问题,是当没有模式匹配或者Grard都是false的时候会DerrorQ这个问题case可以增加一个类似java中default的:<br> <div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #000000;">case Fn of<br></span><span style="color: #000000;"><img src="http://m.tkk7.com/Images/dot.gif"></span><span style="color: #000000;"><br>   _ </span><span style="color: #000000;">-></span><span style="color: #000000;"><br>   true<br>end</span></div> 通过_指代L的ExprQ返回true,而if可以q样Q?br> <div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #0000ff;">if</span><span style="color: #000000;"><br>  </span><span style="color: #000000;"><img src="http://m.tkk7.com/Images/dot.gif"></span><span style="color: #000000;"><br>  true </span><span style="color: #000000;">-></span><span style="color: #000000;"><br>   true<br>end</span></div> 一L道理。case语句另一个需要注意的问题是变量范围Q每个case分支中定义的变量都将默认导出case语句Q也是在case语句l束后可以被引用Q因此一个规则就是每个case分支定义的变量应该一_不然是非法的,~译器会l出警告Q比如:<br> <div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #000000;">f(X) </span><span style="color: #000000;">-></span><span style="color: #000000;"><br>case g(X) of<br>true </span><span style="color: #000000;">-></span><span style="color: #000000;"> A </span><span style="color: #000000;">=</span><span style="color: #000000;"> h(X)</span><span style="color: #000000;">,</span><span style="color: #000000;"> B </span><span style="color: #000000;">=</span><span style="color: #000000;"> A </span><span style="color: #000000;">+</span><span style="color: #000000;"> </span><span style="color: #800000;">7</span><span style="color: #000000;">;<br>false </span><span style="color: #000000;">-></span><span style="color: #000000;"> B </span><span style="color: #000000;">=</span><span style="color: #000000;"> </span><span style="color: #800000;">6</span><span style="color: #000000;"><br>end</span><span style="color: #000000;">,</span><span style="color: #000000;"><br>h(A)</span><span style="color: #000000;">.</span></div> <br>如果执行true分支Q变量A和变量B都被定义Q而如果执行的false分支Q只有变量B被定义,可在case语句执行后,h(A)调用了变量AQ这是不安全的,因ؓ变量A完全可能没有被定义,~译器将l出警告<br><span style="font-weight: bold;">variable 'A' unsafe in 'case' (line 10)</span><br><br> <br><br><span style="font-weight: bold;">14.</span>l出一些稍微复杂的模型匚w例子Q比如用于计数字列表的和、^均倹{长度、查找某元素是否在列表中Q我们把q个模块定义为list:<br> <div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #000000;">-</span><span style="color: #000000;">module(list)</span><span style="color: #000000;">.</span><span style="color: #000000;"><br></span><span style="color: #000000;">-</span><span style="color: #000000;">export([average</span><span style="color: #000000;">/</span><span style="color: #800000;">1</span><span style="color: #000000;">,</span><span style="color: #000000;">sum</span><span style="color: #000000;">/</span><span style="color: #800000;">1</span><span style="color: #000000;">,</span><span style="color: #000000;">len</span><span style="color: #000000;">/</span><span style="color: #800000;">1</span><span style="color: #000000;">,</span><span style="color: #000000;">double</span><span style="color: #000000;">/</span><span style="color: #800000;">1</span><span style="color: #000000;">,</span><span style="color: #000000;">member</span><span style="color: #000000;">/</span><span style="color: #800000;">2</span><span style="color: #000000;">])</span><span style="color: #000000;">.</span><span style="color: #000000;"><br>average(X)</span><span style="color: #000000;">-></span><span style="color: #000000;">sum(X)</span><span style="color: #000000;">/</span><span style="color: #000000;">len(X)</span><span style="color: #000000;">.</span><span style="color: #000000;"><br>sum([H</span><span style="color: #000000;">|</span><span style="color: #000000;">T]) when number(H)</span><span style="color: #000000;">-></span><span style="color: #000000;">H</span><span style="color: #000000;">+</span><span style="color: #000000;">sum(T);<br>sum([])</span><span style="color: #000000;">-></span><span style="color: #800000;">0</span><span style="color: #000000;">.</span><span style="color: #000000;"><br>len([_</span><span style="color: #000000;">|</span><span style="color: #000000;">T])</span><span style="color: #000000;">-></span><span style="color: #800000;">1</span><span style="color: #000000;">+</span><span style="color: #000000;">len(T);<br>len([])</span><span style="color: #000000;">-></span><span style="color: #800000;">0</span><span style="color: #000000;">.</span><span style="color: #000000;"><br>double([H</span><span style="color: #000000;">|</span><span style="color: #000000;">T]) </span><span style="color: #000000;">-></span><span style="color: #000000;"> [</span><span style="color: #800000;">2</span><span style="color: #000000;">*</span><span style="color: #000000;">H</span><span style="color: #000000;">|</span><span style="color: #000000;">double(T)];<br>double([]) </span><span style="color: #000000;">-></span><span style="color: #000000;"> []</span><span style="color: #000000;">.</span><span style="color: #000000;"><br>member(H</span><span style="color: #000000;">,</span><span style="color: #000000;"> [H</span><span style="color: #000000;">|</span><span style="color: #000000;">_]) </span><span style="color: #000000;">-></span><span style="color: #000000;"> true;<br>member(H</span><span style="color: #000000;">,</span><span style="color: #000000;"> [_</span><span style="color: #000000;">|</span><span style="color: #000000;">T]) </span><span style="color: #000000;">-></span><span style="color: #000000;"> member(H</span><span style="color: #000000;">,</span><span style="color: #000000;"> T);<br>member(_</span><span style="color: #000000;">,</span><span style="color: #000000;"> []) </span><span style="color: #000000;">-></span><span style="color: #000000;"> false</span><span style="color: #000000;">.</span><span style="color: #000000;"><br>                <br><br></span></div> l细体会Q利用递归来实玎ͼ比较有趣Q这其实与Lisp中利用尾递归来实现P代是一L道理Q[H|T]的Ş式类似Lisp中的car、cdr操作。_用于指代L的变量,当我们只x此处有变量,但ƈ不关心变量的值的时候用。用分号;来说明是同一个函数定义,只是不同的定义分支,通过模式匚w来决定调用哪个函数定义分支?br>另一个例子,计算各种囑Ş的面U,也是评中给出的例子Q?br> <div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #000000;"><br></span><span style="color: #000000;">-</span><span style="color: #000000;">module(mathStuff)</span><span style="color: #000000;">.</span><span style="color: #000000;"><br></span><span style="color: #000000;">-</span><span style="color: #000000;">export([factorial</span><span style="color: #000000;">/</span><span style="color: #800000;">1</span><span style="color: #000000;">,</span><span style="color: #000000;">area</span><span style="color: #000000;">/</span><span style="color: #800000;">1</span><span style="color: #000000;">])</span><span style="color: #000000;">.</span><span style="color: #000000;"><br>factorial(</span><span style="color: #800000;">0</span><span style="color: #000000;">)</span><span style="color: #000000;">-></span><span style="color: #800000;">1</span><span style="color: #000000;">;<br>factorial(N) when N</span><span style="color: #000000;">></span><span style="color: #800000;">0</span><span style="color: #000000;">-></span><span style="color: #000000;">N</span><span style="color: #000000;">*</span><span style="color: #000000;">factorial(N</span><span style="color: #000000;">-</span><span style="color: #800000;">1</span><span style="color: #000000;">)</span><span style="color: #000000;">.</span><span style="color: #000000;"><br></span><span style="color: #800080;">%计算正方形面U?/span><span style="color: #000000;">Q参数元l的W一个匹配square    <br>area({square</span><span style="color: #000000;">,</span><span style="color: #000000;"> Side}) </span><span style="color: #000000;">-></span><span style="color: #000000;"><br>    Side </span><span style="color: #000000;">*</span><span style="color: #000000;"> Side;<br></span><span style="color: #800080;">%计算圆的面积</span><span style="color: #000000;">Q匹配circle  <br>area({circle</span><span style="color: #000000;">,</span><span style="color: #000000;"> Radius}) </span><span style="color: #000000;">-></span><span style="color: #000000;"><br>   </span><span style="color: #000000;">%</span><span style="color: #000000;"> almost </span><span style="color: #000000;">:-</span><span style="color: #000000;">)<br>   </span><span style="color: #800000;">3</span><span style="color: #000000;"> </span><span style="color: #000000;">*</span><span style="color: #000000;"> Radius </span><span style="color: #000000;">*</span><span style="color: #000000;"> Radius;<br></span><span style="color: #800080;">%计算三角形的面积</span><span style="color: #000000;">Q利用v伦公式,匚wtriangle <br>area({triangle</span><span style="color: #000000;">,</span><span style="color: #000000;"> A</span><span style="color: #000000;">,</span><span style="color: #000000;"> B</span><span style="color: #000000;">,</span><span style="color: #000000;"> C}) </span><span style="color: #000000;">-></span><span style="color: #000000;"><br>   S </span><span style="color: #000000;">=</span><span style="color: #000000;"> (A </span><span style="color: #000000;">+</span><span style="color: #000000;"> B </span><span style="color: #000000;">+</span><span style="color: #000000;"> C)</span><span style="color: #000000;">/</span><span style="color: #800000;">2</span><span style="color: #000000;">,</span><span style="color: #000000;"><br>math</span><span style="color: #000000;">:</span><span style="color: #0000ff;">sqrt</span><span style="color: #000000;">(S</span><span style="color: #000000;">*</span><span style="color: #000000;">(S</span><span style="color: #000000;">-</span><span style="color: #000000;">A)</span><span style="color: #000000;">*</span><span style="color: #000000;">(S</span><span style="color: #000000;">-</span><span style="color: #000000;">B)</span><span style="color: #000000;">*</span><span style="color: #000000;">(S</span><span style="color: #000000;">-</span><span style="color: #000000;">C));<br></span><span style="color: #800080;">%其他</span><span style="color: #000000;"><br>area(Other) </span><span style="color: #000000;">-></span><span style="color: #000000;"><br>   {invalid_object</span><span style="color: #000000;">,</span><span style="color: #000000;"> Other}</span><span style="color: #000000;">.</span><span style="color: #000000;"><br><br></span></div> 执行一下看看:<br> <div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #800000;">1</span><span style="color: #000000;">></span><span style="color: #000000;"> c(mathStuff)</span><span style="color: #000000;">.</span><span style="color: #000000;"><br>{ok</span><span style="color: #000000;">,</span><span style="color: #000000;">mathStuff}<br></span><span style="color: #800000;">2</span><span style="color: #000000;">></span><span style="color: #000000;"> mathStuff</span><span style="color: #000000;">:</span><span style="color: #000000;">area({square</span><span style="color: #000000;">,</span><span style="color: #800000;">2</span><span style="color: #000000;">})</span><span style="color: #000000;">.</span><span style="color: #000000;"><br></span><span style="color: #800000;">4</span><span style="color: #000000;"><br></span><span style="color: #800000;">3</span><span style="color: #000000;">></span><span style="color: #000000;"> mathStuff</span><span style="color: #000000;">:</span><span style="color: #000000;">area({circle</span><span style="color: #000000;">,</span><span style="color: #800000;">2</span><span style="color: #000000;">})</span><span style="color: #000000;">.</span><span style="color: #000000;"><br></span><span style="color: #800000;">12</span><span style="color: #000000;"><br></span><span style="color: #800000;">4</span><span style="color: #000000;">></span><span style="color: #000000;"> mathStuff</span><span style="color: #000000;">:</span><span style="color: #000000;">area({triangle</span><span style="color: #000000;">,</span><span style="color: #800000;">2</span><span style="color: #000000;">,</span><span style="color: #800000;">3</span><span style="color: #000000;">,</span><span style="color: #800000;">4</span><span style="color: #000000;">})</span><span style="color: #000000;">.</span><span style="color: #000000;"><br></span><span style="color: #800000;">2.90474</span><span style="color: #000000;"><br></span><span style="color: #800000;">5</span><span style="color: #000000;">></span><span style="color: #000000;"> mathStuff</span><span style="color: #000000;">:</span><span style="color: #000000;">area({other</span><span style="color: #000000;">,</span><span style="color: #800000;">2</span><span style="color: #000000;">,</span><span style="color: #800000;">3</span><span style="color: #000000;">,</span><span style="color: #800000;">4</span><span style="color: #000000;">})</span><span style="color: #000000;">.</span><span style="color: #000000;"><br>{invalid_object</span><span style="color: #000000;">,</span><span style="color: #000000;">{other</span><span style="color: #000000;">,</span><span style="color: #800000;">2</span><span style="color: #000000;">,</span><span style="color: #800000;">3</span><span style="color: #000000;">,</span><span style="color: #800000;">4</span><span style="color: #000000;">}}<br></span></div> <br>Erlang使用%开始单行注释?br><img src ="http://m.tkk7.com/killme2008/aggbug/123860.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://m.tkk7.com/killme2008/" target="_blank">dennis</a> 2007-06-13 14:36 <a href="http://m.tkk7.com/killme2008/archive/2007/06/13/123860.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss> <footer> <div class="friendship-link"> <p>лǵվܻԴȤ</p> <a href="http://m.tkk7.com/" title="亚洲av成人片在线观看">亚洲av成人片在线观看</a> <div class="friend-links"> </div> </div> </footer> վ֩ģ壺 <a href="http://pjszlw.com" target="_blank">þþƷAVDz18</a>| <a href="http://77663499.com" target="_blank">˳WWW</a>| <a href="http://zhaoxinwo.com" target="_blank">޾ƷĻӰԺ</a>| <a href="http://goldwellib.com" target="_blank">99þþƷëƬѲ</a>| <a href="http://www003924.com" target="_blank">þþþ޾ƷĻ</a>| <a href="http://yuyang0752.com" target="_blank">һƵ </a>| <a href="http://doctor5470.com" target="_blank">Ļ</a>| <a href="http://www-c559.com" target="_blank">þþþ޾ƷŮ</a>| <a href="http://gdporun.com" target="_blank">ѹۿ</a>| <a href="http://ziguang1688.com" target="_blank">AVƷɫ</a>| <a href="http://2030188.com" target="_blank">պavѹۿ</a>| <a href="http://taiyu18.com" target="_blank">ѹëƬ</a>| <a href="http://amgzh.com" target="_blank">ӰԺһ</a>| <a href="http://avyjj.com" target="_blank">ŮƵƵƵҳ</a>| <a href="http://bisilover.com" target="_blank">Ƶ߹ۿվ</a>| <a href="http://hbtelong.com" target="_blank">AëƬƵ</a>| <a href="http://ynkmht.com" target="_blank">ۺһ</a>| <a href="http://leeszewan.com" target="_blank">AVֻ߹ۿ</a>| <a href="http://meixiudashi.com" target="_blank">պƷþþþþ</a>| <a href="http://5g6z.com" target="_blank">˳www߲</a>| <a href="http://xjscr.com" target="_blank">ɫ˵</a>| <a href="http://cg-fun.com" target="_blank">Ʒð׽Ƶ </a>| <a href="http://zaidongmaixi.com" target="_blank">þþþAVƬ</a>| <a href="http://500308k.com" target="_blank">鶹Ƶѹۿ</a>| <a href="http://jiezinet.com" target="_blank">㽶Ƶһ</a>| <a href="http://popodino.com" target="_blank">Ʒþ㽶߿ۿ</a>| <a href="http://42329c.com" target="_blank">97avƵ</a>| <a href="http://flowsns.com" target="_blank">ŮƵaƵȫվһ ŮƵaƵȫվɫ </a>| <a href="http://jte-sh.com" target="_blank">޾Ʒ߹ۿ </a>| <a href="http://922eee.com" target="_blank">ĻۺϾƷһ</a>| <a href="http://chinahongfeng.com" target="_blank">ѹۿҹ</a>| <a href="http://12345ww.com" target="_blank">ǴýƵѹۿ</a>| <a href="http://5shitou.com" target="_blank">av뾫Ʒ</a>| <a href="http://nxeea.com" target="_blank">߳ٸëˮˮ</a>| <a href="http://331927.com" target="_blank">˳ֻˬƵߵӰ</a>| <a href="http://773311h.com" target="_blank">޾ƷۺҰ</a>| <a href="http://cdessc.com" target="_blank">ëɫëƬѹۿ</a>| <a href="http://zbhongtai.com" target="_blank">Ƶ</a>| <a href="http://z88d.com" target="_blank">ҹƷһ鶹</a>| <a href="http://www6yg6yg.com" target="_blank">Ʒۺһ</a>| <a href="http://www-3499.com" target="_blank">ٸһ˳</a>| <script> (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })(); </script> </body>