receive statement in Erlang

Vance Shipley vances@REDACTED
Wed May 16 23:24:28 CEST 2001


karel writes:
}  I would appreciate it if somebody could:
}    - tell me what I am doing wrong
}    - express his thoughts about the style of programming I used


The reason it is crashing is that inside screenloop/2 you end up doing:

	gs:config(Curball,{move,{DX,DY}})

when Curball isn't a valid argument to gs:config.

This is because the receive loop in screenloop/2 is receiving an extra
<Pid> being sent in from init/0.  The reason for this is that you have
the function to send the initial message to each ball process inside the
screenloop/2 function.  This means that everytime you reenter the
screenloop/2 function you send another initial message to the ball function.
Move it into the tail end of init():

	init() ->
	...
		map(fun(X) -> X ! {screenpid, self()} end, Balls),
		screenloop(C,Balls).

Nothe that I have also taken the liberty of changing the message so that
it is more specific than just the <Pid>.


In general your code here is not very robust because you are not checking
the messages which you are receiving.  The screenloop/2 receive statement
is not bad, you are looking for messages which have obviously come from
your self so you can rely on yourself to know they are valid:

	{From, startball, {K,L,M,N,Color}} ->
	{From, moveball, {Curball, {DX, DY}}} ->

These are good.

The trouble here though is that if you get another message, from somewhere,
you won't eat it up and it will stay there forever.  In fact you send
yourself a message which you aren't catching!

	From ! {self(),true};

This is also a bad format.  I'm not sure what you intended here removing
it sure helped!

You should always have a catchall at the end of a receive like maybe:

	Other -> io:format(screenloop: received bogus message ~w~n", [Other])

I would take apart the initball/2 function and have the initial receive
loop in one function and the second in another.  This would allow you to
have:

init1(...) ->
	receive
		{screenpid, Screenpid} ->
			link(Screenpid),
			init2(...);
		Other ->
			init1(...)
	end.

init2(...) ->
	receive
		{A, B} when pid(B) ->
			ball({A, B}}, Screenpid, {X, Y, DX, DY});
		Other ->
			io:format(initball: received bogus message ~w~n", [Other]),
			init2(...)
	end.



And I can't skip the opportunity to complain about tabs vs. spaces. :)
You mix them here which I find makes things hard to read.  Especially
when you aren't consistent!  I know this is my particular rant but let
me leave you with this:

    receive
        Screenpid ->
		    	link(Screenpid)
        end,

Should be:

	receive
		Screenpid ->
			link(Screenpid)
	end,



	-Vance





More information about the erlang-questions mailing list