Two Erlang Finds: Atomic Names and Parameterized Modules

I just watched this video on beebole.com demonstrating how to use mochiweb to build a web application in Erlang using mnesia as the database. It's an informative screencast, but what really grabbed me was one small trick shown in the video and another described in the posted comments.

Atomic Names

In Erlang, you call the function f in module m using the syntax m:f. What I learned from the video is that module and function names in Erlang are atoms and you can substitute variables containing the appropriate atom. This allows you to call a function by name. Here's an example:

1> string:concat("hello ", "world").
"hello world"
2> Module = list_to_atom("string").
string
3> Func = list_to_atom("concat").
concat
4> Module:Func("like", "this").
"likethis"

This was used in the example webapp to dispatch to a handler function based on text found in the request.

Parameterized Modules

A comment by Bob Ippolito clued me in to an experimental and undocumented feature of recent Erlang releases called parameterized modules (pdf) which provide a way of encapsulating state within a module instance. The result is a construct with some similarities to an immutable class in languages like Java with class-based object systems that bundle data and functions that operate on the data into single object.

A parameterized module allows you to instantiate a module with a list of values and then access those values from any function within the module. Parameterized modules can only be used from other modules, not via the Erlang shell. In the example below, talk.erl is the parameterized module and main.erl is an example of a module using the parameterized talk module. You declare a parameterized module by specifying a list as the second argument to 'module'. This will automaticaly define a new/1 function for the parameterized module which clients will use to instantiate a new module instance with a specified list of data.

%% talk.erl
-module(talk, [What]).
-export([talk/0]).

talk() ->
    io:format("~p~n", [What]).
%% main.erl
-module(main).
-export([start/0]).

start() ->
    Cat = talk:new("meow"),
    Dog = talk:new("woof"),
    Cat:talk(),
    Dog:talk(),
    ok.
$ erl
Erlang (BEAM) emulator version 5.6.5 [source] [smp:2] [async-threads:0] [kernel-poll:false]

Eshell V5.6.5  (abort with ^G)
1> c("talk").
{ok,talk}
2> c("main").
{ok,main}
3> main:start().
"meow"
"woof"
ok

That is all.

archived on 2009-03-04 in , ,

blog comments powered by Disqus