[erlang-questions] extending function clauses

Zvi <>
Sat Dec 20 02:42:49 CET 2008


Hi Ittay,

Function caluses in Erlang are just syntactic shugar for case, i.e.

f(Pattern1) -> E1;
f(Pattern2) -> E2;
...
f(PatternN) -> EN.

is equivalent to:

f(X) -> 
 case X of
   f(Pattern1) -> E1;
   f(Pattern2) -> E2;
   ...
   f(PatternN) -> EN
 end.

The function clauses must be defined in consequtive order in the same source
file.

here the textbook shapes example I wrote, to show how to program in Erlang
in OOP style:

========= gen_shape.erl =======
-module(gen_shape).
-export([behaviour_info/1]).

behaviour_info(callbacks) ->
    [{area, 1}];
     
behaviour_info(_Other) ->
    undefined.

========= geometry.erl =======
-module(geometry).

-behaviour(gen_shape).
-export([area/1]). 

area({Module, Shape}) -> Module:area(Shape).


========= rectangle.erl =======
-module(rectangle).
-behaviour(gen_shape).
-export([new/2, area/1]). 

new(Width,Height) when  is_number(Width),
			is_number(Height)
	-> {?MODULE, {Width,Height}}.

area({Width, Height}) -> Width*Height.


========= square.erl =======
-module(square).
-behaviour(gen_shape).
-export([new/1, area/1]). 

new(Size) when is_number(Size) 
	-> {?MODULE, Size}.

area(Size) when is_number(Size) 
	-> Size*Size.


========= circle.erl =======
-module(circle).
-behaviour(gen_shape).
-export([new/1, area/1]). 

new(Radius) when is_number(Radius) 
	-> {?MODULE, Radius}.

area(Radius) when is_number(Radius) 
	-> math:pi()*Radius*Radius.


======= END ============

Example of usage:

19> Shape1 = rectangle:new(5,7).
{rectangle,{5,7}}
20> geometry:area(Shape1).
35
21> Shape2 = circle:new(10).    
{circle,10}
22> geometry:area(Shape2).  
314.1592653589793
23> 
23> Shape3 = square:new(5). 
{square,5}
24> geometry:area(Shape3). 
25
25> 
25> Shape4 = {pentagon,7}.
{pentagon,7}
26> geometry:area(Shape4).
** exception error: undefined function pentagon:area/1

Two easy modifications for this example:

1. It's possible to change this code to use both generic and specific area/1
function (change representation of each shape to be tuple {ModuleName,
ShapeData} and geometry:area/1 to:

area({Module, Shape}) -> Module:area({Module, Shape}).

2. Let's say, we want to derive square from rectange, so in rectange.erl:

new(Size) when is_number(Size) 
	-> new:rectangle(Size, Size).

%% still need to define area/1 b/c it's in behaviour
area(_) -> erlang:error({should,never,be,called}).


Hope this helps,
Zvi


-- 
View this message in context: http://www.nabble.com/extending-function-clauses-tp21091060p21100978.html
Sent from the Erlang Questions mailing list archive at Nabble.com.




More information about the erlang-questions mailing list