ï»??xml version="1.0" encoding="utf-8" standalone="yes"?>成人午夜毛片,精品福利一区二区三区,国产婷婷成人久久av免费高清http://www.aygfsteel.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‰ï¼š 实现ActoråQŒå…¼è°ˆErlangçš„process调度http://www.aygfsteel.com/killme2008/archive/2010/04/13/318182.htmldennisdennisTue, 13 Apr 2010 10:31:00 GMThttp://www.aygfsteel.com/killme2008/archive/2010/04/13/318182.htmlhttp://www.aygfsteel.com/killme2008/comments/318182.htmlhttp://www.aygfsteel.com/killme2008/archive/2010/04/13/318182.html#Feedback0http://www.aygfsteel.com/killme2008/comments/commentRss/318182.htmlhttp://www.aygfsteel.com/killme2008/services/trackbacks/318182.html     Ruby Fiber指南åQˆä¸€åQ‰åŸº¼‹€
    Ruby Fiber指南åQˆäºŒåQ‰å‚æ•îC¼ é€?/a>
   
Ruby Fiber指南åQˆä¸‰åQ‰è¿‡æ»¤å™¨
    Ruby Fiber指南åQˆå››åQ‰è„P代器
    Ruby Actor指南åQˆäº”åQ‰å®žçްActor

    写这个指南的时候,计划是第五章写一个Fiber的应用例子,但是一时没有想到比较好的例子,模仿《Programming in Lua》中的多ä»ÕdŠ¡ä¸‹è²çš„ä¾‹å­ä¹Ÿä¸åˆé€‚ï¼Œå› äØ“Ruby中的异步HttpClientè·Ÿlua˜q˜æ˜¯å¾ˆä¸ä¸€æ ïLš„åQŒä½“çŽîC¸äº†Fiber的优炏V€‚因此,˜q™ç¬¬äº”节一直拖着没写ã€?br />     恰åéy最˜q‘在ž®ç»„中做了一‹Æ¡Erlang的分享,有äh问到Erlang调度器的实现问题åQŒè¿™å—我没注意过åQŒé‚£æ—¶å€™å°±æ ÒŽ®æˆ‘对coroutine实现actor的想法做了下解释åQŒåŽæ¥æ€è€ƒäº†ä¸‹é‚£ä¸ªè§£é‡Šæ˜¯é”™è¯¯çš„,Erlang的调度器是抢占式的,而通过coroutine实现的actor调度却是非抢占的åQŒä¸¤è€…还是截然不同的。我在ã€?a href="http://www.aygfsteel.com/killme2008/archive/2010/03/23/316273.html">Actor、Coroutineå’ŒContinuation的概忉|¾„æ¸?/a>》中提到coroutine可以实现actor风格åQŒactorè·Ÿcoroutineòq¶æ²¡æœ‰å¿…然的联系åQŒè¿™½‹‡æ–‡ç« çš„目的ž®±åœ¨äºŽè¯æ˜Žè¿™ä¸€ç‚¹ï¼Œä½¿ç”¨Ruby Fiber实现一个简单的actor风格的库åQŒæ•´ä¸ªä»£ç ä¸åˆ?00行。后面还会谈到这个实现的¾~ºç‚¹åQŒä»¥åŠæˆ‘对Erlang调度器实现的理解ã€?br />
    首先是monkey patchåQŒç»™Threadå’ŒFiber¾cÕdŠ ä¸Šä¸¤ä¸ªæ–¹æ³•ï¼Œåˆ†åˆ«ç”¨äºŽèŽ·å–å½“å‰¾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的运行,每次挑选适当的actoròq¶æ‰§è¡Œï¼Œå¯ä»¥æƒŒ™±¡è°ƒåº¦å™¨å†…部应该维护一个等待调度的actor队列åQŒScheduler每次从队列里取出一个actoròq¶æ‰§è¡Œï¼Œæ‰§è¡Œå®Œä¹‹åŽå–下一个actor执行åQŒä¸æ–­åó@环持¾l­è¿™ä¸ªè¿‡½E‹ï¼›åœ¨æ²¡æœ‰actor可以调度的时候,调度器应该让出执行权。因此调度器本èín也是一个FiberåQŒå®ƒå†…部有个queueåQŒç”¨äºŽç»´æŠ¤ç­‰å¾…调度的actoråQ?br />
module FiberActor
  
class Scheduler
    
def initialize
      @queue
=[]
      @running
=false
    end

    
def run
      
return if @running
      @running
=true
      
while true
        
#取出队列中的actoròq¶æ‰§è¡?/span>
        while actor=@queue.shift
          begin
            actor.fiber.resume
          rescue 
=> ex
            puts 
"actor resume error,#{ex}"
          end
        end
        
#没有ä»ÕdŠ¡åQŒè®©å‡ºæ‰§è¡Œæƒ
        Fiber.yield
      end
    end

    
def reschedule
      
if @running
        
#已经启动åQŒåªæ˜¯è¢«æŒ‚è“våQŒé‚£ä¹ˆå†‹Æ¡æ‰§è¡?/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´æŠ¤ä¸€ä¸ªmailboxåQŒç”¨æ¥å­˜å‚¨æŽ¥æ”¶åˆ°çš„æ¶ˆæ¯ã€‚最重要的是receive原语的实玎ͼŒæˆ‘们˜q™é‡Œå¾ˆç®€å•,不搞模式匚w…åQŒåªæ˜¯æŽ¥æ”¶æ¶ˆæ¯ã€‚receive的工作流½E‹å¤§æ¦‚是˜q™æ ·åQŒåˆ¤æ–­mailbox中有没有消息åQŒæœ‰æ¶ˆæ¯çš„话åQŒå–å‡ºæ¶ˆæ¯åÆˆè°ƒç”¨block处理åQŒæ²¡æœ‰æ¶ˆæ¯çš„话就yield让出执行权ã€?br />
module FiberActor  
  
class Actor
    attr_accessor :fiber
    
#定义¾cÀL–¹æ³?/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

    
#¾l™actor发送消æ?/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用于启动一个actoråQŒå†…部其实是创徏了一个fiberòq¶åŒ…装成actor¾l™ç”¨æˆø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|
        
#收到pingåQŒè¿”回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°çš„实现基本上是revactor˜q™ä¸ªåº“的实现原理ã€?a >revactor是一个rubyçš„actor库,它的实现ž®±æ˜¯åŸÞZºŽFiberåQŒåƈ且支持消息的模式匚w…å’Œthread之间的actor调度åQŒæœ‰å…´è¶£åœ°å¯ä»¥åŽ»çŽ©ä¸‹ã€‚æ›´˜q›ä¸€æ­¥ï¼Œå…¶å®žé‡‡ç”¨è½»é‡¾U§å½E‹æ¥æ¨¡æ‹Ÿactor风格早就不是新鲜ä¸ÀL„åQŒæ¯”如在cn-erlounge的第四次会议ä¸?/a>ž®±æœ‰ä¸¤ä¸ªtopic是关于这个,一个是51.com利用åŸÞZºŽucontext的实现的¾c»erlang˜q›ç¨‹æ¨¡åž‹åQŒä¸€ä¸ªæ˜¯è®æ€¸–伟的CERL。可以想见,他们的基本原理跟本文所描述不会有太大差别,那么面对的问题也是一栗÷€?br />
     采用coroutine实现actor的主要缺点如下:
1、因为是非抢占式åQŒè¿™ž®Þp¦æ±‚actor不能有阻塞操作,ä»ÖM½•é˜Õd¡žæ“ä½œéƒ½éœ€è¦å¼‚步化。IO可以使用异步IOåQŒæ²¡æœ‰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¿ç¨‹å¤šä¸ªè°ƒåº¦å™¨ï¼Œ¾cÖM¼¼erlang smp那样来解军_•个调度器的问题。但是如调度效率˜q™æ ·çš„问题是很难解决的。相反,erlangçš„actor实现ž®×ƒ¸æ˜¯é€šè¿‡coroutineåQŒè€Œæ˜¯è‡ªå·±å®žçŽ°ä¸€å¥—ç±»ä¼¼os的调度程序ã€?br />     首先明确一点,Erlangçš„process的调度是抢占式的åQŒè€Œéžcouroutine的协作式的。其‹Æ¡ï¼ŒErlang早期版本是只有一个调度器åQŒè¿è¡Œåœ¨ä¸€ä¸ªçº¿½E‹ä¸ŠåQŒéšç€erts的发展,现在erlang的调度器已经支持smpåQŒæ¯ä¸ªcpuå…Œ™”一个调度器åQŒåƈ且可以明¼‹®æŒ‡å®šå“ªä¸ªè°ƒåº¦å™¨¾l‘定到哪个cpu上。第三,Erlang的调度也是采用优先队åˆ?æ—‰™—´ç‰‡è½®è¯¢çš„æ–¹å¼åQŒæ¯ä¸ªè°ƒåº¦å™¨å…Œ™”一ä¸?span id=":2v1">ErtsRunQueueåQ?/span>ErtsRunQueue内部又分ä¸ÞZ¸‰ä¸?/span>ErtsRunPrioQueue队列åQŒåˆ†åˆ«å¯¹åº”high,maxå’Œnormal,low的优先çñ”åQŒå…¶ä¸­normalå’Œlowå…Þq”¨ä¸€ä¸ªé˜Ÿåˆ—;在Erlang中时间片是以reduction为单位,你可以将reduction理解成一‹Æ¡å‡½æ•°è°ƒç”¨ï¼Œæ¯ä¸ªè¢«è°ƒåº¦çš„process能执行的reduction‹Æ¡æ•°æ˜¯æœ‰é™çš„。调度器每次都是从max队列开始寻扄¡­‰å¾…调度的processòq¶æ‰§è¡Œï¼Œå½“å‰è°ƒåº¦çš„é˜Ÿåˆ—å¦‚æžœäØ“½Iºæˆ–者执行的reductions­‘…过限制åQŒé‚£ä¹ˆå°±é™ä½Žä¼˜å…ˆ¾U§ï¼Œè°ƒåº¦ä¸‹ä¸€ä¸ªé˜Ÿåˆ—ã€?br />
   从上面的描述可以看出åQŒErlang优秀的地方不仅在于actor风格的轻量çñ”processåQŒå¦ä¸€ä¸ªå¼ºæ‚çš„地方ž®±æ˜¯å®ƒçš„¾c»os的调度器åQŒå†åŠ ä¸ŠOTP库的完美支持åQŒè¿™ä¸æ˜¯ä¸€èˆ¬æ–¹æ¡ˆèƒ½å±±å¯¨çš„ã€?br />     
    
  


]]>
Erlang½Ž€ä»‹çš„PPTåQˆè¾¾äººå‹¿å…¥ï¼‰http://www.aygfsteel.com/killme2008/archive/2010/04/12/318031.htmldennisdennisMon, 12 Apr 2010 02:45:00 GMThttp://www.aygfsteel.com/killme2008/archive/2010/04/12/318031.htmlhttp://www.aygfsteel.com/killme2008/comments/318031.htmlhttp://www.aygfsteel.com/killme2008/archive/2010/04/12/318031.html#Feedback0http://www.aygfsteel.com/killme2008/comments/commentRss/318031.htmlhttp://www.aygfsteel.com/killme2008/services/trackbacks/318031.html


]]>
Rabbitmq的网¾lœå±‚‹¹…析http://www.aygfsteel.com/killme2008/archive/2009/11/29/304079.htmldennisdennisSun, 29 Nov 2009 04:00:00 GMThttp://www.aygfsteel.com/killme2008/archive/2009/11/29/304079.htmlhttp://www.aygfsteel.com/killme2008/comments/304079.htmlhttp://www.aygfsteel.com/killme2008/archive/2009/11/29/304079.html#Feedback5http://www.aygfsteel.com/killme2008/comments/commentRss/304079.htmlhttp://www.aygfsteel.com/killme2008/services/trackbacks/304079.html     Rabbitmq是一个MQ¾pȝ»ŸåQŒä¹Ÿž®±æ˜¯æ¶ˆæ¯ä¸­é—´ä»Óž¼Œå®ƒå®žçŽîCº†AMQP 0.8规范åQŒç®€å•来说就是一个TCP的广播服务器。AMQP协议åQŒä½ å¯ä»¥¾cÀL¯”JMSåQŒä¸˜q‡JMS仅仅是java领域内的API规范åQŒè€ŒAMQP比JMS更进一步,它有自己的wire-level protocolåQŒæœ‰ä¸€å¥—可¾~–程的协议,中立于语­a€ã€‚简单介¾läº†Rabbitmq之后åQŒè¿›å…¥æ­£é¢˜ã€?br />     Rabbitmq充分利用了Erlangçš„åˆ†å¸ƒå¼ã€é«˜å¯é æ€§ã€åÆˆå‘ç­‰ç‰ÒŽ€§ï¼Œé¦–先看它的一个结构图åQ?br />


˜q™å¼ å›‘Ö±•çŽîCº†Rabbitmq的主要组件和¾l„äšg之间的关¾p»ï¼Œå…·ä½“到监控树的结构,我画了一张图åQ?br />






    ™å¶å±‚是rabbit_sup supervisoråQŒå®ƒè‡›_°‘有两个子˜q›ç¨‹åQŒä¸€ä¸ªæ˜¯rabbit_tcp_client_supåQŒç”¨æ¥ç›‘控每个connection的处理进½E? rabbit_readerçš„supervisor;rabbit_tcp_listener_sup是监控tcp_listenerå’? tcp_acceptor_supçš„supervisoråQŒtcp_listener里启动tcp服务器,监听端口åQŒåƈ且通过tcp_acceptor_sup启动N个tcp_accetporåQŒtcp_acceptor发è“vacceptè¯äh±‚åQŒç­‰å¾…客æˆïL«¯˜qžæŽ¥;tcp_acceptor_sup负责监控˜q™äº›acceptor。这张图已经能给你一个大体的印象ã€?/strong>
   
    讲完大概åQŒè¿›å…¥ç»†èŠ‚ï¼Œè¯´è¯´å‡ ä¸ªæˆ‘è§‰çš„å€¼çš„æ³¨æ„çš„åœ°æ–¹ï¼š
1�strong>tcp_accepto.erl,r对于accept采用的是异步方式
åQŒåˆ©ç”?strong>prim_inet:async_accept/2
æ–? 法,此模块没有被文档化,是otp库内部ä‹Éç”?通常来说没必要ä‹É用这一模块åQŒgen_tcp:accept/1已经­‘›_¤ŸåQŒä¸˜q‡rabbitmq是广播程 序,因此采用了异步方式。ä‹É用async_acceptåQŒéœ€è¦æ‰“patchåQŒä»¥ä½¿å¾—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¶å‘acceptoråQŒè¿™åœ¨é«˜òq¶å‘下、大量连接情况下有效率优势,¾cÖM¼¼java现在的nio框架采用多个reactor¾cÖM¼¼åQŒæŸ¥çœ‹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‹Æ¡æ‰§è¡ŒæŸä¸ªå‡½æ•°FåQŒå¯ä»¥é€šè¿‡lists:foreach¾l“合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_oneåQŒè¿™æ˜¯äؓ什么呢åQ?br /> ˜q™ç‰µæ‰¯åˆ°simple_one_for_one的几个特点:
1)simple_one_for_one内部保存child是ä‹É用dictåQŒè€Œå…¶ä»–策略是使用liståQŒå› æ­¤simple_one_for_one更适合child频繁创徏销毁、需要大量child˜q›ç¨‹çš„æƒ…况,具体来说例如¾|‘络˜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 spectåQŒä¼ å…¥å‚æ•°liståQŒä¼šè‡ªåЍ˜q›è¡Œå‚æ•°åˆåÆˆã€?strong>在一个地方定义好child spec之后åQŒå…¶ä»–地方只要start_child传入参数卛_¯å¯åЍchild˜q›ç¨‹åQŒç®€åŒ–child都是同一¾cÕdž‹˜q›ç¨‹æƒ…况下的¾~–程ã€?br />
åœ? rabbitmq中,tcp_acceptor_sup的子˜q›ç¨‹éƒ½æ˜¯tcp_acceptor˜q›ç¨‹å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_reader¾cÕdž‹åQŒåœ¨ 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_reader˜q›ç¨‹ã€?br />
4ã€?strong>协议的解析,消息的读å?/strong>˜q™éƒ¨åˆ†ä¹Ÿéžå¸¸å·§å¦™åQŒè¿™ä¸€éƒ¨åˆ†ä¸»è¦åœ¨rabbit_reader.erl中,对于协议的解析没有采用gen_fsmåQŒè€Œæ˜¯å®žçŽ°äº†ä¸€ä¸ªåé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_callback˜q™ä¸ªæ–ÒŽ³•上:
switch_callback(OldState, NewCallback, Length) ->
    %发è“v一个异步recvè¯äh±‚åQŒè¯·æ±‚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 startåQŒåå•†å‚æ•?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>
1åQ‰tcp server的启动过½E‹ï¼š

2åQ‰ä¸€ä¸ªclient˜qžæŽ¥ä¸Šæ¥çš„处理过½E‹ï¼š


    ž®ç»“åQšä»Žä¸Šé¢çš„分析可以看å‡?rabbitmq的网¾lœå±‚是非常健壮和高效的,通过层层监控åQŒå¯¹æ¯ä¸ªå¯èƒ½å‡ºçŽ°çš„é£Žé™©ç‚¹éƒ½åšäº†è€ƒè™‘åQŒåƈ且利用了prim_net模块做异步IO处理。分层也是很清晰åQŒå°†ä¸šåŠ¡å¤„ç†æ¨¡å—éš”ç¦»åˆ°client_sup监控下的子进½E‹ï¼Œž®†ç½‘¾lœå¤„理细节和业务逻辑分离。在协议的解析和业务处理上虽然没有采用gen_fsmåQŒä½†æ˜¯ä¹Ÿå®žçŽ°äº†ä¸€å¥—ç±»ä¼¼çš„çŠ¶æ€æœºæœºåˆ¶åQŒé€šè¿‡åŠ¨æ€æ›¿æ¢Callback来模拟状态的变迁åQŒéžå¸¸åéy妙。如果你要实çŽîC¸€ä¸ªtcp serveråQŒå¼ºçƒˆæŽ¨èä»Žrabbitmqä¸­æ‰£å‡ø™¿™ä¸ªç½‘¾lœå±‚åQŒä½ åªéœ€è¦å®žçŽ°è‡ªå·Þqš„业务处理模块卛_¯æ‹¥æœ‰ä¸€ä¸ªé«˜æ•ˆã€å¥å£®ã€åˆ†å±‚清晰的TCP服务器ã€?br />

]]>
Erlang Web Shell(update)http://www.aygfsteel.com/killme2008/archive/2009/11/19/302967.htmldennisdennisThu, 19 Nov 2009 11:22:00 GMThttp://www.aygfsteel.com/killme2008/archive/2009/11/19/302967.htmlhttp://www.aygfsteel.com/killme2008/comments/302967.htmlhttp://www.aygfsteel.com/killme2008/archive/2009/11/19/302967.html#Feedback0http://www.aygfsteel.com/killme2008/comments/commentRss/302967.htmlhttp://www.aygfsteel.com/killme2008/services/trackbacks/302967.html   
   下午搞了ä¸?a >Erlang web shellåQŒå¯ä»¥åœ¨web™åµé¢ä¸Šåƒeshell那样˜q›è¡Œäº¤äº’式的Erlang¾~–程åQŒæ–¹ä¾¿å­¦ä¹ å’Œ‹¹‹è¯•。这样一来,一ä¸?a >erlwshž®±å¯ä»¥æœåŠ¡å¤šä¸ªclientåQŒåªè¦ä½ æœ‰ç½‘¾lœå’Œ‹¹è§ˆå™¨ï¼Œéšæ—¶éšåœ°å¯ä»¥æ•²ä¸Šå‡ è¡Œerlang看看¾l“果。代码很½Ž€å•,ž®×ƒ¸å¤šè¯´äº†ï¼Œæœ‰å…´­‘£çš„看看åQŒé€šè¿‡mochiwebçš„http chunk¾~–码åQŒclient通过Ajax Postæ–¹å¼æäº¤ã€‚çœ¼è§äØ“å®žï¼Œçœ‹çœ‹˜qè¡Œæˆªå›¾åQ?br />




    工程在google code上: http://code.google.com/p/erlwsh/
   
    安装很简单,首先¼‹®ä¿ä½ å·²¾lå®‰è£…了ErlangåQŒæŽ¥ä¸‹æ¥åQ?br />
svn checkout http://erlwsh.googlecode.com/svn/trunk/ erlwsh-read-only
cd erlwsh-read-only
scripts/install_mochiweb.sh
make
./start.sh

    å› äØ“éœ€è¦ä‹É用mochiwebåQŒæ‰€ä»¥æä¾›äº†ä¸‹è²òq¶è‡ªåŠ¨å®‰è£…çš„è„šæœ¬åQŒè¿™æ˜¯litaocheng的大作。启动后讉K—® http://localhost:8000/shell 卛_¯åQŒhave fun.





]]>
etså’Œdets的效率徏è®?/title><link>http://www.aygfsteel.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://www.aygfsteel.com/killme2008/archive/2007/09/27/148764.html</guid><wfw:comment>http://www.aygfsteel.com/killme2008/comments/148764.html</wfw:comment><comments>http://www.aygfsteel.com/killme2008/archive/2007/09/27/148764.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.aygfsteel.com/killme2008/comments/commentRss/148764.html</wfw:commentRss><trackback:ping>http://www.aygfsteel.com/killme2008/services/trackbacks/148764.html</trackback:ping><description><![CDATA[   ets表的底层是由哈希表实现的,不过ordered_set例外,它是由åã^衡二叉树实现的ã€?所以不½Ž¡æ˜¯æ’å…¥˜q˜æ˜¯æŸ¥æ‰¾,set的效率要比ordered_seté«?采用set˜q˜æ˜¯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表插入binary¾cÕdž‹å…ƒç»„也很划算。我们应该尽可能采用binaries来实现字½W¦ä¸²æˆ–æ— ¾cÕdž‹çš„大数据å?<img src ="http://www.aygfsteel.com/killme2008/aggbug/148764.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.aygfsteel.com/killme2008/" target="_blank">dennis</a> 2007-09-27 16:33 <a href="http://www.aygfsteel.com/killme2008/archive/2007/09/27/148764.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Erlang之IO¾~–程http://www.aygfsteel.com/killme2008/archive/2007/09/27/148747.htmldennisdennisThu, 27 Sep 2007 08:03:00 GMThttp://www.aygfsteel.com/killme2008/archive/2007/09/27/148747.htmlhttp://www.aygfsteel.com/killme2008/comments/148747.htmlhttp://www.aygfsteel.com/killme2008/archive/2007/09/27/148747.html#Feedback2http://www.aygfsteel.com/killme2008/comments/commentRss/148747.htmlhttp://www.aygfsteel.com/killme2008/services/trackbacks/148747.html file模块åQšæ‰“å¼€ã€è¯»ã€å†™ã€å…³é—­æ–‡ä»¶å·²¾læ“ä½œç›®å½•çš„æ–ÒŽ³•基本都在˜q™é‡Œ

filename模块åQšæä¾›åã^台独立方式用于操¾U‰|–‡ä»¶å

filelib模块åQšfile模块的扩展,提供了更多的实用工具åQŒåœ¨file模块基础上构å»?br />
io模块åQšä¸€¾pÕdˆ—用于操作打开的文件的æ–ÒŽ³•åQŒè§£æžæ ¼å¼ã€æ ¼å¼åŒ–输出½{‰ç­‰ã€?br />
1.打开文äšgåQ?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.è¯Õd–åQ?br /> (1)如果以一个Erlang term的方式读取,采用:
io:read(F,'').
其中½W¬äºŒä¸ªå‚数是提示½W¦ï¼Œç”¨äºŽåœ¨æ ‡å‡†è¾“å…¥æ—¶ä½œäØ“æç¤ºã€?br /> ˜q™ä¸ªæ–ÒŽ³•有一个变形read/3
read(IoDevice, Prompt, StartLine)
½W¬ä¸‰ä¸ªå‚数用于指定开始行数ã€?br />
(2)如果是按字节è¯Õd–åQŒæ–‡ä»¶å¿…™åÀLŒ‰raw模式打开采用åQ?br /> {ok, Data}=file:read(F,100).

(3)按行è¯Õd–åQ?br /> io:get_line(F, '').

(4)è¯Õd–整个文äšg的内容:
{ok,Binary}=file:read_file("data1.dat").
注意˜q”回的是一个binary¾cÕdž‹

(5)随机è¯Õd–åQ?br /> {ok,Binary}=file:pread(F, 22, 46).

其中½W¬äºŒä¸ªå‚数是开始位¾|®ï¼Œ½W¬ä¸‰ä¸ªå‚数是è¯Õd–的长度,˜q”回的也是binary¾cÕdž‹ã€?br />
3.写入文äšgåQ?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   与~w¾cÖM¼¼åQŒä¸˜q‡å½“多行时将自动换行
~n   昄¡„¶åQŒæ¢è¡Œç¬¦

åQ?åQ‰å†™å…¥æ•´ä¸ªæ–‡ä»Óž¼š
file:write_file(File, IO)

其中IO可以为list、integer或者binary¾cÕdž‹

å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记录¾cÕdž‹åQŒé‡Œé¢æ‹¥æœ‰æ–‡ä»¶çš„具体信息å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 />





]]>
½Ž€å•çš„web server性能‹¹‹è¯•http://www.aygfsteel.com/killme2008/archive/2007/08/29/141036.htmldennisdennisWed, 29 Aug 2007 10:10:00 GMThttp://www.aygfsteel.com/killme2008/archive/2007/08/29/141036.htmlhttp://www.aygfsteel.com/killme2008/comments/141036.htmlhttp://www.aygfsteel.com/killme2008/archive/2007/08/29/141036.html#Feedback4http://www.aygfsteel.com/killme2008/comments/commentRss/141036.htmlhttp://www.aygfsteel.com/killme2008/services/trackbacks/141036.html阅读全文

]]>
Erlang ring benchmarkhttp://www.aygfsteel.com/killme2008/archive/2007/08/04/134417.htmldennisdennisSat, 04 Aug 2007 09:46:00 GMThttp://www.aygfsteel.com/killme2008/archive/2007/08/04/134417.htmlhttp://www.aygfsteel.com/killme2008/comments/134417.htmlhttp://www.aygfsteel.com/killme2008/archive/2007/08/04/134417.html#Feedback0http://www.aygfsteel.com/killme2008/comments/commentRss/134417.htmlhttp://www.aygfsteel.com/killme2008/services/trackbacks/134417.html˜q™é‡Œ
    不过我分析了˜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,1000åQ‰ï¼Œä¹Ÿå°±æ˜?000个进½E‹ï¼Œ1000‹Æ¡æ¶ˆæ¯åó@环,æ€Õd…±300万次消息传递,¾l“æžœåœ?.5¿U’左叻I¼Œ˜q™ä¹Ÿæ˜¯ç›¸å½“惊人的¾l“果。有人用haskellå’Œscheme各实çŽîCº†ä¸€ä¸ªç‰ˆæœ¬ï¼Œæœ‰å…´­‘£çš„看看˜q™é‡Œå’?a >˜q™é‡Œ




]]>
Erlang入门åQˆäº”åQ‰â€”—补é?/title><link>http://www.aygfsteel.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://www.aygfsteel.com/killme2008/archive/2007/07/24/132011.html</guid><wfw:comment>http://www.aygfsteel.com/killme2008/comments/132011.html</wfw:comment><comments>http://www.aygfsteel.com/killme2008/archive/2007/07/24/132011.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.aygfsteel.com/killme2008/comments/commentRss/132011.html</wfw:commentRss><trackback:ping>http://www.aygfsteel.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)BinaryåQŒç”¨äºŽè¡¨½CºæŸŒD‰|œªçŸ¥ç±»åž‹çš„内存区域<br>比如åQ?br>1> <strong> <<10,20>>.</strong> <br><<10,20>> <br>2> <strong> <<"ABC">>.</strong><br> <<65,66,67>> <br><br>2åQ‰ReferenceåQŒé€šè¿‡è°ƒç”¨mk_ref/0产生的运行时的unique term<br><br>3)StringåQŒå­—½W¦ä¸²åQŒErlang中的字符串用双引号包括è“v来,其实也是list。编译时期,两个邻近的字½W¦ä¸²ž®†è¢«˜qžæŽ¥èµäh¥åQŒæ¯”å¦?string" "42" ½{‰ä­häº?"string42"<br><br>4)RecordåQŒè®°å½•类型,与c语言中的struct¾cÖM¼¼åQŒæ¨¡å—可以通过-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å¯¹è·¯å¾„查找文äšgåQŒè€Œæ˜¯åœ¨ä½ å½“前Erlangçš„lib目录˜q›è¡ŒæŸ¥æ‰¾ã€?br><br><span style="font-weight: bold;">4.try表达å¼?/span>åQŒtry表达式可以与catch¾l“合使用å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>不仅如此åQŒtry˜q˜å¯ä»¥ä¸Žafter¾l“合使用åQŒç±»ä¼¼java中的try..finallyåQŒç”¨äºŽè¿›è¡Œæ¸…除作用,比如å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>åQˆList ComprehensionsåQ‰ï¼Œå‡½æ•°å¼è¯­­a€ç‰ÒŽ€§ä¹‹ä¸€åQŒErlang中的语法¾cÖM¼¼åQ?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>ä½¿ç”¨çš„æ—¶å€™åœ¨å®åå‰åŠ ä¸ªé—®åøP¼ŸåQŒæ¯”å¦?ConståQŒReplacementž®†æ’入宏出现的位¾|®ã€‚ç³»¾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Œè¡¨½CÞZ¸æ»¡èƒö前者条件时执行以下代码 <br></dd><dt><code>-endif.</code> </dt><dd>if¾lˆæ­¢½W?/dd></dl>假设å®?define(Square(X),X*X).用于计算òqÏx–¹åQŒé‚£ä¹??Xž®†è¿”回X表达式的字符串åŞ式,¾cÖM¼¼C语言ä¸?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的输å‡ÞZº†åQŒè¡Œæ•°ã€æ¨¡å—名以及参数<br> 7ã€?span style="font-weight: bold;">Process Dictionary</span>åQŒæ¯ä¸ªè¿›½E‹éƒ½æœ‰è‡ªå·Þqš„process dictionaryåQŒç”¨äºŽå­˜å‚¨è¿™ä¸ªè¿›½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>1åQ‰èŠ‚ç‚¹ä¹‹é—´çš„˜qžæŽ¥é»˜è®¤æ˜¯transitiveåQŒä¹Ÿž®±æ˜¯å½“节点A˜qžæŽ¥äº†èŠ‚ç‚¹BåQŒèŠ‚ç‚¹B˜qžæŽ¥äº†èŠ‚ç‚¹CåQŒé‚£ä¹ˆèŠ‚ç‚¹A也与节点C互相˜qžæŽ¥<br>可以通过启动节点时指定参æ•?connect_all false来取消默认行ä¸?br><br>2åQ‰éšè—èŠ‚ç‚¹ï¼ŒæŸäº›æƒ…å†µä¸‹ï¼Œä½ å¸Œæœ›è¿žæŽ¥ä¸€ä¸ªèŠ‚ç‚¹è€Œä¸åŽ»è¿žæŽ¥å…¶ä»–èŠ‚ç‚¹ï¼Œä½ å¯ä»¥é€šè¿‡åœ¨èŠ‚ç‚¹å¯åŠ¨æ—¶æŒ‡å®š-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">启动一个Erlang¾pȝ»Ÿä½œäؓ节点å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 exp2åQŒå½“exp1˜q”回false之后åQŒå°±ä¸ä¼šåŽÀL±‚å€?br>exp2åQŒè€Œæ˜¯ç›´æŽ¥˜q”回falseåQŒè€Œ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://www.aygfsteel.com/killme2008/aggbug/132011.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.aygfsteel.com/killme2008/" target="_blank">dennis</a> 2007-07-24 11:23 <a href="http://www.aygfsteel.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://www.aygfsteel.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://www.aygfsteel.com/killme2008/archive/2007/07/15/130384.html</guid><wfw:comment>http://www.aygfsteel.com/killme2008/comments/130384.html</wfw:comment><comments>http://www.aygfsteel.com/killme2008/archive/2007/07/15/130384.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.aygfsteel.com/killme2008/comments/commentRss/130384.html</wfw:commentRss><trackback:ping>http://www.aygfsteel.com/killme2008/services/trackbacks/130384.html</trackback:ping><description><![CDATA[    Lich Ray写了个帖子ã€?a >函数式编½E‹è¯­­a€æ›²é«˜å’Œå¯¡åQ?/a>》,用快速排序的例子来说明函数式¾~–程在表达思想斚w¢æ¯”命令式语言更容易,其实˜q™ä¸€ç‚ÒŽ¯‹åº¸ç½®ç–‘,如果你正在读或者读˜q‡SICP的话。文中给了haskell、schemeå’Œjavascript的实çŽîC¾‹å­ï¼Œæˆ‘也凑趣写了个Erlang版本åQŒhaskell我不了解ž®×ƒ¸è¯´äº†åQŒå…¶ä»–实现分别如下:<br>schemeå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;">(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的话åQŒErlangçš„list其实跟schemeçš„list是一æ ïLš„åQŒç”šè‡Œ™¿žå®šä¹‰çš„åŸºæœ¬é«˜é˜¶å‡½æ•°éƒ½ä¸€æ øP¼šmap,filteråQŒappend½{‰ç­‰,利用lists模块提供的filterå’Œappendå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;">    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Œä¸¤è€…最显著的不同是åQŒscheme使用了条件语句ifåQŒè€Œ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)判断来源于严格确定对象是什么类åQˆclassåQ‰ï¼Œä¸æ˜¯˜q™ä¸ª¾cÕd®ƒž®±æ²¡æœ‰ç›¸åº”çš„æ–ÒŽ³•åQŒè€Œäº‹å®žä¸Š¾cÖM¸Ž¾cÕdž‹˜q™ä¸¤ä¸ªæ¦‚å¿µåÆˆä¸æ˜¯ä¸€è‡´çš„åQŒå¯¹è±¡çš„¾cÕdž‹æ›´åº”该根据对象能够做什么来军_®šã€‚扯˜qœäº†åQŒè¿™åªæ˜¯æˆ‘读ã€?a >å¤Þp¸ªçš„链çŽ?/a>》得来的感受åQŒå¦‚果对模式匚w…˜q˜æœ‰æ€€ç–‘的话,让我们回到这个例子的Erlang版本åQŒä»£ç ä¸­æˆ‘们调用了两‹Æ¡filter˜q›è¡Œå…¨è¡¨æ‰«æå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º†å±•现模式匚w…å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;">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不支持模式匹配。请注意rubyòq¶æ²¡æœ‰å°¾é€’归优化åQŒå› æ­¤ä¸Šé¢çš„代码在数¾l„æ¯”è¾ƒå¤§çš„æ—¶å€™ä¼šå¯ÆD‡´æ ˆæº¢å‡ºï¼Œæƒ³ç”¨ruby做函数式¾~–程应该ž®½é‡å¤šä‹É用åó@环和map,filter,collect½{‰è¾…助高阶函数ã€?br>    另外一个Erlang与ruby、scheme比较重要的区别是Erlang的变量只能赋å€ég¸€‹Æ¡ï¼ˆæˆ–者说¾l‘定åQ‰ï¼Œä¹Ÿå°±æ˜¯single assignment。这个特点与Erlang所要满­‘³çš„˜qè¡Œåœºæ™¯æœ‰ç´§å¯†å…³¾p»ï¼Œå½“ç³»¾lŸå‘生错误时åQŒå°±å¯ä»¥ä»ŽåŽŸæ¥çš„å€¼é‡æ–°å¯åŠ¨ä“QåŠ¡ï¼Œè€Œä¸ç”¨æ‹…å¿ƒç”±äºŽå˜é‡å€¼çš„å˜åŒ–å¯ÆD‡´¾pȝ»Ÿæ¢å¤å›°éš¾ã€?br><br><br><br><br><img src ="http://www.aygfsteel.com/killme2008/aggbug/130384.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.aygfsteel.com/killme2008/" target="_blank">dennis</a> 2007-07-15 16:11 <a href="http://www.aygfsteel.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://www.aygfsteel.com/killme2008/archive/2007/06/29/127099.htmldennisdennisFri, 29 Jun 2007 08:33:00 GMThttp://www.aygfsteel.com/killme2008/archive/2007/06/29/127099.htmlhttp://www.aygfsteel.com/killme2008/comments/127099.htmlhttp://www.aygfsteel.com/killme2008/archive/2007/06/29/127099.html#Feedback0http://www.aygfsteel.com/killme2008/comments/commentRss/127099.htmlhttp://www.aygfsteel.com/killme2008/services/trackbacks/127099.html
1.首先,分布式Erlang的实现提供了自有的安全机制来预防未经授权的Erlang¾pȝ»Ÿè®‰K—®ã€‚Erlang¾pȝ»Ÿä¸Žåˆ«çš„æœºå™¨è¿›è¡Œäº¤äº’时必须有同æ ïLš„magic cookie,保存在一个称ä¸?erlang.cookie的文件中åQŒäؓ了在两台不同机器间测试,需要编辑一ä»?erlang.cookie,内容随便åQŒæ¯”如:
just_test

然后ž®†è¿™ä»½æ–‡ä»¶æ‹·è´åˆ°windows环境变量HOMEPATH所在的目录 åQŒæ¯”如我的是C:\Documents and Settings\AdminåQŒè€Œlinux拯‚´åˆ°çŽ¯å¢ƒå˜é‡?HOME指向的目录,比如我这里是/root。特别注意一点,linuxçš?erlang.cookieæ–‡äšg需要设¾|®æƒé™äØ“-r--------åQŒä¹Ÿž®±æ˜¯400åQŒä»…所有者可读:
chmod 400 .erlang.cookie

2.因䨓Erlang中的node名称是name@hoståQŒhost是计½Ž—机名,因此在两台机器上都需要将计算机名和ip加进hostsæ–‡äšgåQŒè¿™ä¸ªæ–‡ä»¶åœ¨linux下是åœ?etc/hostsåQŒä½ å¯ä»¥ç”¨vi¾~–辑如下åQ?br>
127.0.0.1  localhost localhost
x.x.x.x    zane      zane
   #windows机器的ip和计½Ž—机å?/span>
åQŒhosts在windows¾pȝ»Ÿçš„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 -nameåQŒåœ¨æ­¤ä¹‹å‰éœ€è¦å¯åЍepmd˜q›ç¨‹åQŒå®ƒè´Ÿè´£æ˜ å°„½W¦å·ååˆ°æœºå™¨åœ°å€
在两个机器都执行åQ?br>epmd -daemon

4.è‡Ïx­¤é…ç½®å®ŒæˆåQŒå¯ä»¥æµ‹è¯•下Erlang分布式编½E‹åœ¨ä¸åŒçš„æœºå™¨å’Œ¾pȝ»Ÿä¹‹é—´äº†ï¼ˆæ¯”如ã€?a href="http://www.aygfsteel.com/killme2008/archive/2007/06/15/124547.html">Erlang入门(ä¸?--分布式编½E?/a>》中的ping pong例子åQ‰ï¼Œvery cool!



]]>
Erlang入门åQˆå››åQ‰â€”—错误处理和鲁棒æ€?/title><link>http://www.aygfsteel.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://www.aygfsteel.com/killme2008/archive/2007/06/25/126156.html</guid><wfw:comment>http://www.aygfsteel.com/killme2008/comments/126156.html</wfw:comment><comments>http://www.aygfsteel.com/killme2008/archive/2007/06/25/126156.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.aygfsteel.com/killme2008/comments/commentRss/126156.html</wfw:commentRss><trackback:ping>http://www.aygfsteel.com/killme2008/services/trackbacks/126156.html</trackback:ping><description><![CDATA[     摘要:     åŽÖMº†­‘Ÿç¦å·žï¼Œäº‹æƒ…没搞定,托给同学帮忙处理了,回家休息了两天就来上班了。回家这几天最大的收获是第四次重读《深入Java虚拟机》,以前不大明了的章节豁然开朗,有种开½Hçš„æ„Ÿè§‰åQŒæ°´åˆ°æ¸ æˆï¼Œçœ‹æ¥æŠ€æœ¯çš„学习˜q˜æ˜¯æ€¥ä¸æ¥ã€?nbsp;   闲话不提åQŒç‘ô¾l­Erlang的学习,上次学习到分布式¾~–程的章节,剩下三章分别是错误处理、构造健壮的¾pȝ»Ÿå’Œæ‚™å¹ï¼Œé”™è¯¯å¤„理å’?..  <a href='http://www.aygfsteel.com/killme2008/archive/2007/06/25/126156.html'>阅读全文</a><img src ="http://www.aygfsteel.com/killme2008/aggbug/126156.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.aygfsteel.com/killme2008/" target="_blank">dennis</a> 2007-06-25 17:10 <a href="http://www.aygfsteel.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://www.aygfsteel.com/killme2008/archive/2007/06/15/124547.htmldennisdennisFri, 15 Jun 2007 09:33:00 GMThttp://www.aygfsteel.com/killme2008/archive/2007/06/15/124547.htmlhttp://www.aygfsteel.com/killme2008/comments/124547.htmlhttp://www.aygfsteel.com/killme2008/archive/2007/06/15/124547.html#Feedback0http://www.aygfsteel.com/killme2008/comments/commentRss/124547.htmlhttp://www.aygfsteel.com/killme2008/services/trackbacks/124547.htmlErlang¾~–程手册åQŒå€¼çš„好好è¯ÖM¸€éã€?br />     所谓分布式的Erlang应用是运行在一¾pÕdˆ—Erlang节点¾l„成的网¾lœä¹‹ä¸Šã€‚è¿™æ ïLš„¾pȝ»Ÿçš„æ€§è´¨ä¸Žå•一节点上的Erlang¾pȝ»Ÿòq¶æ²¡æœ‰ä»€ä¹ˆä¸åŒã€‚分布式˜q™æ˜¯ä¸?#8220;大词”åQŒErlang从语­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”回我们自己的进½E‹name

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

node(Item)
˜q”回原来Item的节点名¿UŽÍ¼ŒItem可以是Pid,引用åQˆreferenceåQ‰æˆ–者端å?port)

disconnect_node(Nodename)
从节点Nodename断开�br />
    节点是分布式Erlang的核心概å¿üc€‚在一个分布式Erlang应用中,术语åQˆterm)节点(nodeåQ‰æ„å‘³ç€ä¸€ä¸ªå¯ä»¥åŠ å…¥åˆ†å¸ƒå¼transactions的运行系¾lŸã€‚通过一个称为net kernal的特ŒDŠè¿›½E‹ï¼Œä¸€ä¸ªç‹¬ç«‹çš„Erlang¾pȝ»Ÿå¯ä»¥æˆäؓ一个分布式Erlang¾pȝ»Ÿçš„一部分。当net kernal˜q›ç¨‹å¯åŠ¨çš„æ—¶å€™ï¼Œæˆ‘ä»¬¿U°ç³»¾lŸæ˜¯aliveçš„ã€?br />
    与远½E‹èŠ‚ç‚¹ä¸Šçš„è¿›½E‹è¿›è¡Œé€šä¿¡åQŒä¸ŽåŒä¸€èŠ‚ç‚¹å†…çš„˜q›ç¨‹é€šä¿¡åªæœ‰ä¸€ç‚¹ä¸åŒï¼š
  
   {Name, Node} ! Mess.
昄¡„¶åQŒéœ€è¦æŽ¥æ”¶æ–¹å¢žåŠ ä¸€ä¸ªå‚æ•°Node用于指定接受˜q›ç¨‹æ‰€åœ¨çš„节点。节点的name一般是用@隔开的atom¾cÕdž‹åQŒæ¯”如pong@dennisåQŒè¡¨½Cø™®¡½Ž—æœºåäØ“dennis上的pong节点。通过执行:
erl -sname pong
ž®†åœ¨æ‰§è¡Œçš„计½Ž—机中创å»ÞZ¸€ä¸ªèŠ‚ç‚¹pongã€‚äØ“äº†è¿è¡Œä¸‹é¢çš„ä¾‹å­åQŒä½ å¯èƒ½éœ€è¦ä¸¤å°è®¡½Ž—机åQŒå¦‚果只有一収ͼŒåªè¦åŒæ—¶å¼€ä¸¤ä¸ªErlang¾pȝ»Ÿò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æ–ÒŽ³•åQŒpingæ–ÒŽ³•有两个参敎ͼŒä¸€ä¸ªæ˜¯å‘送消息的‹Æ¡æ•°åQŒä¸€ä¸ªå°±æ˜¯è¿œ½E‹èŠ‚ç‚¹çš„name了,也就是我们将要创建的˜q›ç¨‹pong的所在节炏V€‚start_pong创徏一个调用函数pong的进½E‹ï¼Œòq¶æ³¨å†Œäؓ名字pongåQˆå› æ­¤åœ¨pingæ–ÒŽ³•中可以直接发送消息给pong)ã€?br />     我是在windows机器上测试,首先打开两个cmd½H—口åQŒåƈcd到Erlang的安装目录下的bin目录åQŒæ¯”如C:\Program Files\erl5.5.3\bin,ž®†ä¸Šé¢çš„½E‹åºå­˜äØ“tut17.erlåQŒåƈ拯‚´åˆ°åŒä¸€ä¸ªç›®å½•下。我们将创徏两个节点åQŒä¸€ä¸ªå«ping@dennis,一个叫pong@dennis,其中dennis是我的机器名。见下图åQ?br />
采用同样的命�br />
erl -sname ping
创徏ping节点。然后在pong节点下执行start_pong()åQ?br />

OK,˜q™æ ·ž®±åœ¨èŠ‚ç‚¹pong上启动了pong˜q›ç¨‹åQŒç„¶åŽåœ¨ping节点调用start_pingåQŒä¼ å…¥å‚数就是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()]).
pong˜q›ç¨‹å¯åЍPing_Node节点上的˜q›ç¨‹ping。具体结果不再给出ã€?br />


    



]]>
Erlang入门åQˆäºŒåQ‰â€”åÆˆå‘ç¼–½E?/title><link>http://www.aygfsteel.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://www.aygfsteel.com/killme2008/archive/2007/06/14/124355.html</guid><wfw:comment>http://www.aygfsteel.com/killme2008/comments/124355.html</wfw:comment><comments>http://www.aygfsteel.com/killme2008/archive/2007/06/14/124355.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.aygfsteel.com/killme2008/comments/commentRss/124355.html</wfw:commentRss><trackback:ping>http://www.aygfsteel.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Œåº”用开发者可以设计这样一个ç‘ô承体¾p…R€?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›ç¨‹çš„æ ‡è¯†ç¬¦åQˆPidåQ‰ã€?br>如果在一个已知进½E‹Pid1中执行:<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> 那么åQŒPid2仅仅能被Pid1可见åQŒErlang¾pȝ»Ÿçš„安全性就构徏在限制进½E‹æ‰©å±•的基础上ã€?br><br><span style="font-weight: bold;">2.˜q›ç¨‹é—´é€šä¿¡</span><br>    Erlang˜q›ç¨‹é—´çš„通信只能通过发送消息来实现å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½•的有效的Erlang¾l“æž„å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://www.aygfsteel.com/Images/dot.gif"></span><span style="color: #000000;"><br>end</span></div> <br>    每一个Erlang˜q›ç¨‹éƒ½æœ‰ä¸€ä¸?#8220;邮箱”åQŒæ‰€æœ‰å‘送到˜q›ç¨‹çš„æ¶ˆæ¯éƒ½æŒ‰ç…§åˆ°è¾¾çš„顺序存储在“邮箱”里,上面所½Cºçš„æ¶ˆæ¯Message1,Message2åQŒå½“它们ä¸?#8220;邮箱”里的消息匚w…åQŒåƈ且约束(GuardåQ‰é€šè¿‡åQŒé‚£ä¹ˆç›¸åº”çš„ActionNž®†æ‰§è¡Œï¼Œòq¶ä¸”receive˜q”回的是ActionN的最后一条执行语句的¾l“果。Erlangå¯?#8220;邮箱”里的消息匚w…æ˜¯æœ‰é€‰æ‹©æ€§çš„åQŒåªæœ‰åŒ¹é…çš„æ¶ˆæ¯ž®†è¢«è§¦å‘相应的ActionåQŒè€Œæ²¡æœ‰åŒ¹é…çš„æ¶ˆæ¯ž®†ä»ç„¶ä¿ç•™åœ¨“邮箱”里。这一机制保证了没有消息会é˜Õ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™è¿›½E‹Pid发送消息{self(),abc}åQŒåˆ©ç”¨self˜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;">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://www.aygfsteel.com/Images/dot.gif"></span><span style="color: #000000;"><br>end</span></div> 通过模式匚w…å†›_®šåªæœ‰Pid1˜q›ç¨‹å‘送的消息才接受ã€?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;">%不是以上3¿Uæ¶ˆæ?/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>åŸÞZºŽ˜q›ç¨‹çš„æ¶ˆæ¯ä¼ é€’机制可以很å®ÒŽ˜“地实现有限状态机åQˆFSMåQ‰ï¼ŒçŠ¶æ€ä‹É用函数表½Cºï¼Œè€Œäº‹ä»¶å°±æ˜¯æ¶ˆæ¯ã€‚具体不再展开<br><br><span style="font-weight: bold;">4.­‘…时讄¡½®</span><br>    Erlang中的receive语法可以æ·ÕdŠ ä¸€ä¸ªé¢å¤–é€‰é¡¹åQštimeoutå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://www.aygfsteel.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表达式返回一个整数timeåQˆæ¯«¿U’çñ”别)åQŒæ—¶é—´çš„¾_„¡¡®½E‹åº¦ä¾èµ–于Erlang在操作系¾lŸæˆ–者硬件的实现。如果在time毫秒内,没有一个消息被选中åQŒè¶…时设¾|®å°†ç”Ÿæ•ˆåQŒä¹Ÿž®±æ˜¯ActionTž®†æ‰§è¡Œã€‚time有两个特ŒDŠå€û|¼š<br>1)<span style="font-weight: bold;">infinity</span>(æ— ç©·å¤?åQŒinfinity是一个atomåQŒæŒ‡å®šäº†­‘…时讄¡½®ž®†æ°¸˜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>    ä¸ÞZº†¾l™è¿›½E‹å‘送消息,我们需要知道进½E‹çš„PidåQŒä½†æ˜¯åœ¨æŸäº›æƒ…况下:在一个很大系¾lŸé‡Œé¢æœ‰å¾ˆå¤šçš„全局serversåQŒæˆ–è€…äØ“äº†å®‰å…¨è€ƒè™‘éœ€è¦éšè—è¿›½E‹Pidã€‚äØ“äº†è¾¾åˆ°å¯ä»¥å‘é€æ¶ˆæ¯ç»™ä¸€ä¸ªä¸çŸ¥é“Pid的进½E‹çš„目的åQŒæˆ‘们提供了注册˜q›ç¨‹çš„办法,¾l™è¿›½E‹ä»¬æ³¨å†Œåå­—åQŒè¿™äº›åå­—å¿…™åÀL˜¯atomã€?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与进½E‹Pid联系èµä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‹çš„PidåQŒå¦‚果没有进½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>    所有的ERLANG˜q›ç¨‹éƒ½æœ‰ä¸€ä¸ªPid与一个他们共有的¿UîCØ“Group Leader相关联,当一个新的进½E‹è¢«åˆ›å¾çš„æ—¶å€™å°†è¢«åŠ å…¥åŒä¸€ä¸ªè¿›½E‹ç»„。最初的¾pȝ»Ÿ˜q›ç¨‹çš„Group Leaderž®±æ˜¯å®ƒè‡ªíw«ï¼Œå› æ­¤å®ƒä¹Ÿæ˜¯æ‰€æœ‰è¢«åˆ›å¾˜q›ç¨‹åŠå­˜q›ç¨‹çš„Group Leader。这ž®±æ„å‘³ç€Erlang的进½E‹è¢«¾l„织ä¸ÞZ¸€‹‚µTreeåQŒå…¶ä¸­çš„æ ¹èŠ‚ç‚¹å°±æ˜¯ç¬¬ä¸€ä¸ªè¢«åˆ›å¾çš„è¿›½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 Leader䏸™¿›½E‹çš„Leader <br><br><span style="font-weight: bold;">8.</span>Erlang的进½E‹æ¨¡åž‹å¾ˆå®ÒŽ˜“åŽÀLž„建Client-Server的模型,书中有一节专门讨è®ÞZº†˜q™ä¸€ç‚¹ï¼Œç€é‡å¼ºè°ƒäº†æŽ¥å£çš„设计以及抽象层‹Æ¡çš„隔离问题åQŒä¸¾˜»è¯‘了ã€?br><br> <img src ="http://www.aygfsteel.com/killme2008/aggbug/124355.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.aygfsteel.com/killme2008/" target="_blank">dennis</a> 2007-06-14 17:12 <a href="http://www.aygfsteel.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://www.aygfsteel.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://www.aygfsteel.com/killme2008/archive/2007/06/14/124226.html</guid><wfw:comment>http://www.aygfsteel.com/killme2008/comments/124226.html</wfw:comment><comments>http://www.aygfsteel.com/killme2008/archive/2007/06/14/124226.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.aygfsteel.com/killme2008/comments/commentRss/124226.html</wfw:commentRss><trackback:ping>http://www.aygfsteel.com/killme2008/services/trackbacks/124226.html</trackback:ping><description><![CDATA[<img alt="Erlang logo" src="http://www.aygfsteel.com/killme2008/admin/erlang_small.gif" align="right" border="0"> <h1>Erlang前世今生</h1> <hr> <h1>1982 - 1985</h1> 我们使用äº?> 20¿Uè¯­­a€˜q›è¡Œäº†ç”µä¿¡è¡Œä¸šçš„¾~–程实验åQŒç»“论是åQšè¿™æ ïLš„语言需要是一门高度的抽象的语­a€æ‰èƒ½è¾‘Öˆ°ç”Ÿäñ”力目标ã€?¾l™æˆ‘们留下印象的有:List,Prolog,Parlog ...) <h1>1985 - 86</h1> 我们使用Lisp,Prolog,Parlog½{‰è¯­­a€˜q›è¡Œäº†å®žéªŒï¼Œ¾l“论是:˜q™æ ·çš„语­a€éœ€è¦åŽŸç”Ÿæ”¯æŒçš„òq¶å‘控制和容错处理,òq¶ä¸”执行模型必须没有使用回溯。(排除了Listå’ŒProlog.) 而且它必™åÀL‹¥æœ‰åƈ发粒度比如一个异步的电话˜q›ç¨‹å¯ä»¥ç”¨è¯­­a€çš„一个进½E‹è¡¨½Cºï¼ˆæŽ’除了ParlogåQ‰ã€‚最后我们不得不开发一门我们自å·Þqš„语言åQŒå®ƒæ‹¥æœ‰ Lisp,Prologå’ŒParlog的特性,但内¾|®äº†òq¶å‘和容错处理ã€? <h1>1987</h1> ½W¬ä¸€‹Æ¡ä‹É用erlang˜q›è¡Œå®žéªŒã€? <h1>1988</h1> ACS/DunderåQˆé¡¹ç›?½W¬ä¸€é˜¶æ®µåQšå¤–来用户ä‹É用erlang˜q›è¡ŒPABX(专用自动交换分机)功能的原型构建, <em>Erlang走出了实验室åQ?/em> <h1>1989</h1> <p> ACS/DunderåQˆé¡¹ç›?½W¬äºŒé˜¶æ®µåQšé‡æ–°æ”¹é€ äº†å®Œæ•´çš„MD-110¾pȝ»Ÿçš?/10åQŒç»“æž?相比于ä‹É用PLEX的构建有>>10倍的效率提高åQ? </p> <h1>1990</h1>  Erlang正式以ISS'90标准发布åQŒè¿™å¸¦æ¥ä¸å°‘的新用户åQŒæ¯”如Bellcoreã€? <h1>1991</h1> Erlang发布了更快的版本实现¾l™ç”¨æˆøP¼ŒErlang应用于电ä¿?91åQˆé¡¹ç›®ï¼Ÿå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://www.aygfsteel.com/killme2008/aggbug/124226.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.aygfsteel.com/killme2008/" target="_blank">dennis</a> 2007-06-14 09:28 <a href="http://www.aygfsteel.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://www.aygfsteel.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://www.aygfsteel.com/killme2008/archive/2007/06/13/123860.html</guid><wfw:comment>http://www.aygfsteel.com/killme2008/comments/123860.html</wfw:comment><comments>http://www.aygfsteel.com/killme2008/archive/2007/06/13/123860.html#Feedback</comments><slash:comments>4</slash:comments><wfw:commentRss>http://www.aygfsteel.com/killme2008/comments/commentRss/123860.html</wfw:commentRss><trackback:ping>http://www.aygfsteel.com/killme2008/services/trackbacks/123860.html</trackback:ping><description><![CDATA[    读erlang.org上面的Erlang Course四天教程<br><span style="font-weight: bold;">1.</span>æ•°å­—¾cÕdž‹åQŒéœ€è¦æ³¨æ„ä¸¤ç‚?br>1åQ‰B#Val表示以B˜q›åˆ¶å­˜å‚¨çš„æ•°å­—Valå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;">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ž®±æ˜¯10˜q›åˆ¶çš?äº?br>2åQ?Char表示字符Charçš„ascii¾~–码åQŒæ¯”å¦?A表示65<br><br><span style="font-weight: bold;">2.</span>比较难以¾˜»è¯‘的概念——atomåQŒå¯ä»¥ç†è§£æˆå¸”R‡åQŒå®ƒå¯ä»¥åŒ…含ä»Ö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“æž„ž®±æ˜¯å„个语言都有的liståQˆåˆ—表)å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>1åQ‰å˜é‡å¿…™åÖM»¥å¤§å†™å­—母或者下划线开å¤ß_¼Œå¯ä»¥åŒ…含字母、下划线和@<br>2åQ‰å˜é‡åªèƒ½ç»‘定一‹Æ¡ï¼Œä¹Ÿå°±æ˜¯æ‰€è°“çš„Single Assignment。或者以一般的说法ž®±æ˜¯åªèƒ½èµ‹å€ég¸€‹Æ¡ï¼Œå…¶å®žErlangòq¶æ²¡æœ‰èµ‹å€ÆD¿™æ ïLš„æ¦‚念,=号也是用于验证匹配ã€?br><br><span style="font-weight: bold;">7.</span>模式匚w…â€”—Pattern MatchingåQŒErlang的模式匹配非常强大,看了<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中函数的定义必须在一个模块内åQˆModuleåQ‰ï¼Œòq¶ä¸”模块和函数的名称都必™åÀL˜¯atomåQŒå‡½æ•°çš„参数可以是ä“Q何的Erlang¾cÕdž‹æˆ–者数据结构,函数要被调用需要从模块中导出,函数调用的åŞ式类ä¼û|¼š<br>moduleName:funcName(Arg1,Arg2,...).<br>写我们的½W¬ä¸€ä¸ªErlang½E‹åºåQŒäh见ähçˆÞqš„Hello Worldå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(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.erlåQŒåœ¨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™ä¸€è¡Œå£°æ˜Žäº†æ¨¡å—helloWorldåQŒå‡½æ•°å¿…™åÕ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> 而这一行声明导出的函数åQŒrun/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> 大写开头的是变量NameåQŒè°ƒç”¨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])  %输出1åQŒä¹Ÿž®±æ˜¯åˆ—表的headåQŒç±»ä¼¼Lispçš„car<br>    tl([1,2,3,4])  %输出[2,3,4],也就是列表的tail,¾cÖM¼¼Listçš„cdr<br></span></div> <br><span style="font-weight: bold;">10.</span>常见Shell命ä×oåQ?br>1åQ?span style="font-weight: bold;">h().</span> 用来打印最˜q‘çš„20条历史命ä»?br>2åQ?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>   执行½W¬n条历史命ä»?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€‚用于限制变量的¾cÕdž‹å’ŒèŒƒå›ß_¼Œæ¯”如å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º†æ–¹ä¾¿æ¯”较å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: #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»¥åŠå‚数列表,比如调用我们的第一个Erlang½E‹åºå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语句åQŒif语句的结构如下:<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://www.aygfsteel.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çš„æ—¶å€™ä¼šå¯ÆD‡´erroråQŒè¿™ä¸ªé—®é¢˜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://www.aygfsteel.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„çš„ExpråQŒè¿”回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://www.aygfsteel.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)调用了变量AåQŒè¿™æ˜¯ä¸å®‰å…¨çš„ï¼Œå› äØ“å˜é‡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伦公式,匚w…triangle <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://www.aygfsteel.com/killme2008/aggbug/123860.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.aygfsteel.com/killme2008/" target="_blank">dennis</a> 2007-06-13 14:36 <a href="http://www.aygfsteel.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"> <a href="http://www.aygfsteel.com/" title="狠狠久久亚洲欧美专区_中文字幕亚洲综合久久202_国产精品亚洲第五区在线_日本免费网站视频">狠狠久久亚洲欧美专区_中文字幕亚洲综合久久202_国产精品亚洲第五区在线_日本免费网站视频</a> </div> </footer> Ö÷Õ¾Ö©Öë³ØÄ£°å£º <a href="http://" target="_blank">½¨Ë®ÏØ</a>| <a href="http://" target="_blank">õ·ÁêÊÐ</a>| <a href="http://" target="_blank">ÑÉêÈ</a>| <a href="http://" target="_blank">Ðû»¯ÏØ</a>| <a href="http://" target="_blank">ÖÎÏØ¡£</a>| <a href="http://" target="_blank">ÐÂÃÜÊÐ</a>| <a href="http://" target="_blank">ÐûººÏØ</a>| <a href="http://" target="_blank">ÒËÐËÊÐ</a>| <a href="http://" target="_blank">ÉîË®ˆ¶Çø</a>| <a href="http://" target="_blank">ʯÃÞÏØ</a>| <a href="http://" target="_blank">Äþ°²ÊÐ</a>| <a href="http://" target="_blank">ÂÞÆ½ÏØ</a>| <a href="http://" target="_blank">±£¶¨ÊÐ</a>| <a href="http://" target="_blank">²ÔÉ½ÏØ</a>| <a href="http://" target="_blank">ɳÑóÏØ</a>| <a href="http://" target="_blank">³ÎÂõÏØ</a>| <a href="http://" target="_blank">Î÷ÏçÏØ</a>| <a href="http://" target="_blank">É£ÈÕÏØ</a>| <a href="http://" target="_blank">Ê¯ÈªÏØ</a>| <a href="http://" target="_blank">¿ÂÆºÏØ</a>| <a href="http://" target="_blank">¾üÊÂ</a>| <a href="http://" target="_blank">äµË®ÏØ</a>| <a href="http://" target="_blank">Ìì¾þÏØ</a>| <a href="http://" target="_blank">µÂ²ýÏØ</a>| <a href="http://" target="_blank">Õã½­Ê¡</a>| <a href="http://" target="_blank">캵ÂÏØ</a>| <a href="http://" target="_blank">ÖÐÑôÏØ</a>| <a href="http://" target="_blank">Ä«Öñ¹¤¿¨ÏØ</a>| <a href="http://" target="_blank">»·áÏØ</a>| <a href="http://" target="_blank">ÈÕÕÕÊÐ</a>| <a href="http://" target="_blank">ÓÒÓñÏØ</a>| <a href="http://" target="_blank">Î÷²ýÊÐ</a>| <a href="http://" target="_blank">̨ÖÝÊÐ</a>| <a href="http://" target="_blank">¿í³Ç</a>| <a href="http://" target="_blank">Û©³ÇÏØ</a>| <a href="http://" target="_blank">¹óÄÏÏØ</a>| <a href="http://" target="_blank">¸£½¨Ê¡</a>| <a href="http://" target="_blank">ÂêÄÉË¹ÏØ</a>| <a href="http://" target="_blank">ËÉÑôÏØ</a>| <a href="http://" target="_blank">ÓÀÐÞÏØ</a>| <a href="http://" 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>