5

From the Learn You Some Erlang for Great Good!

Another special case is when the timeout is at 0:

flush() -> 
  receive
   _ -> flush() 
  after 0 -> 
    ok 
  end
.

When that happens, the Erlang VM will try and find a message that fits one of the available patterns. In the case above, anything matches. As long as there are messages, the flush/0 function will recursively call itself until the mailbox is empty. Once this is done, the after 0 -> ok part of the code is executed and the function returns.

I don't understand purpose of after 0. After reading above text I thought it was like after infinity (waiting forever) but I changed a little the flush function:

flush2() ->
  receive
    _ -> timer:sleep(1000), io:format("aa~n"), flush()
  after 0 ->
    okss
  end
.

flush3() ->
  receive
    _ -> io:format("aa~n"), flush()
  after 0 ->
    okss
  end
.

In the first function it waits 1 second and in the second function it doesn't wait.
In both cases it doesn't display a text (aa~n).
So it doesn't work as after infinity.

If block between the receive and the after are not executed then above 2 codes can be simplified to:

flush4() ->
  okss
.

What I am missing?

ps. I am on the Erlang R16B03-1, and author of the book was, as fair I remember, was on the Erlang R13.

2240
  • 1,547
  • 2
  • 12
  • 30
Darek Nędza
  • 1,420
  • 1
  • 12
  • 19

4 Answers4

15

Every process has a 'mailbox' -- message queue. Messages can be fetched by receive. if there is no messages in the queue. after part specifies how much time 'receive will wait for them. So after 0 -- means process checking (by receive ) if any messages in the queue and if queue is empty immediately continue to next instructions.

It can be used for instance if we want periodically check if any messages here and to do something (hopefully helpful) if there is no messages.

2240
  • 1,547
  • 2
  • 12
  • 30
Odobenus Rosmarus
  • 5,870
  • 2
  • 18
  • 21
5

Consider after 0 to be finally.

Consider the use of after 0 to process receives with a priority: http://learnyousomeerlang.com/more-on-multiprocessing#selective-receives

May this different look on things enlighten you.

fenollp
  • 2,406
  • 1
  • 15
  • 14
4

You can play with the following shell command to understand the effect of the after command:

4> L = fun(G) ->                            
4> receive                                  
4> stop -> ok;                               
4> M -> io:format("received ~p~n",[M]), G(G)
4> after 0 ->                               
4> io:format("no message~n")                
4> end
4> end.
#Fun<erl_eval.6.80484245>
5> F = fun() -> timer:sleep(10000),          
5> io:format("end of wait for messages, go to receive block~n"),
5> L(L)end.
#Fun<erl_eval.20.80484245>
6> spawn(F).                                 
<0.46.0>
end of wait for messages, go to receive block
no message
7> P1 = spawn(F).
<0.52.0>
8> P1 ! hello.   
hello
end of wait for messages, go to receive block
received hello
no message
9> P2 ! hello, P2 ! stop.
* 1: variable 'P2' is unbound
8> P2 = spawn(F).        
<0.56.0>
9> P2 ! hello, P2 ! stop.
stop
end of wait for messages, go to receive block
received hello
10> 
Pascal
  • 13,977
  • 2
  • 24
  • 32
0

If you do not intend to use a nested receive, rather than using "after" part, I think a better approach is to use "Unexpected ->" variable to handle all unmatched messages.

Mohan
  • 129
  • 8