ANNOUNCE ex11 release two

Joe Armstrong joe@REDACTED
Fri Jan 23 09:28:04 CET 2004


> > 
> > 	B = swButton:make(Win ......)
> > 	S = self(),
> > 	B ! {onClick, fun(X) -> S ! {wrapper, X} end},
> > 	...
> > 
> > 	loop(...).
> > 
> >         
> >         loop(...) ->
> > 	   receive
> > 		{wrapper, X} ->
> > 		    Do something
> > 	        ...
> > 	   end
> 
> What about allowing the caller to use a term for the message
> if they just want a message sent:
> 
> 	B = swButton:make(Win ....),
> 	S = self(),
> 	B ! {onClick, {S, wrapper} end},
> 
> 	loop () ->
> 		receive
> 		{wrapper, X} ->
> 		end,
> 		loop().
> 
> Easy to tell a tuple and a fun apart; if it is a tuple it is a
> two tuple of {Pid, Tag}; which results in the message {Tag, X}
> being sent to to Pid.  This way the caller doesn't need to
> build a fun, and waste all the bytecode and memory on a fun to
> just send itself a tagged message.
> 
> Of course, this is only really useful if a large number of apps
> are written this way.  :)
> 
> 

To answer this you need to understand what a fun really is:

If we start with this code:

	G = fun(X) -> S ! {wrapper, X} end,
	G(X)

I'll explain (almost) what happens:

To implement funs we perform "lambda lifting" and abstracts out
all the bound variables in the body of the fun.

In the expression 

	G = fun(X) -> S ! {wrapper, X} end,

	S is bound (ie fixed)
	X is free

The compiler transforms 


	G = fun(X) -> S ! {wrapper, X} end,
	G(X)

Into
	G = {'magic-tag-45-67', [S]},
	applyLambdas(G, X)

plus a new function

        applyLambdas({'magic-tag-45-67',[S]}, X) -> S ! {wrapper,X} end)

This is all hidden from the user (sometimes the magic tag seeps
out then the fun crashes :-) - 

<<note this is "almost" what happens - in the real implementation
a special internal representation of funs is used for efficiency>>

The point to note is that code like

	B ! {onClick, fun(X) -> S ! {wrapper, X} end}

and 
	B ! {onClick, {S,  Wrapper}}

both end up sending a single message to B

In the first case the message is

	{'magic-fun-123',[S]}

and in the second

	{S, Wrapper}

Now back to your original comment:

> 
> Easy to tell a tuple and a fun apart; if it is a tuple it is a
> two tuple of {Pid, Tag}; which results in the message {Tag, X}
> being sent to to Pid.  This way the caller doesn't need to
> build a fun, and waste all the bytecode and memory on a fun to
> just send itself a tagged message.

This isn't really true, sending a fun in a message *is* just sending
a tagged message and because of the way this message is represented
internally it might even use less space and be more efficient.

Also, evaluating funs should be more efficient than pattern matching in
receive statements.

As for the "wasted memory" I have tried hard to make ex11 as 
inefficient as possible - the resulting code is "blindingly fast" on
my 400 MHz celerion - a few bytes here or there don't make much difference 
on todays machines.

If you look at where all the time goes you will observe the following

	1) An incredibly small amount of time is spent in the
	   high level widget code - my guess is < 1%
	2) A fair bit of time is spent in the widget top loops
	   handling expose events and mouse move events (say 30%)
	3) A lot of time is spent in the X server 70%

All of this means that user land code can be written as inefficiently as
possible - the bottleneck is in the X-server itself - hardly surprising
just putting a single character on the display must involve hundreds, or
even thousands of instructions - just think of moving all those little
pixels ....

Cheers

/Joe




More information about the erlang-questions mailing list