how to hold lists

Richard A. O'Keefe <>
Mon May 15 03:06:33 CEST 2006


"Yani Dzhurov" <> wrote:
	I need these lists to simulate some kind of enumarations.
	...
	This procedure looks pretty stupid in this example.
	But when I have large enums and need to insert new values in it /{Monday,
	Tuesday, Wednesday,SOME_OTHER_WEEK_DAY, Thursday, Friday, Saturday=20,
	Sunday}/ it would be easy to maintain. 
	
	If someone else has a better idea, pls advise me:)
	
The big question is this:
    When you write "I ... need to insert new values ..."
    do you mean that *YOU* need to insert new values (perhaps with a
    text editor) and then a re-compile is OK,
    or that you need a PROGRAM acting perhaps as your agent to do
    this at run time?

If it is the former, there is a mantra that I would like you to recite
several times a day:
    CODE is DATA!

Let's say you want the following operations on an enumeration:

    (1) Return the number of enumerals, N.
    (2) Convert from an integer 1..N to the corresponding enumeral.
    (3) Convert from an enumeral to the corresponding integer.
    (4) Test whether a symbol is a member of the set.
    (5) Return all the enumerals in order as a list.

Let's say you would be happy with this as a module

    -module(ModuleName).
    -export([size/0,from_integer/1,to_integer/1,includes/1,members/0]).

    size() -> N.

    from_integer(1) -> Enumeral_1;
    ...
    from_integer(N) -> Enumeral_N.

    to_integer(Enumeral_1) -> 1;
    ...
    to_integer(Enumeral_N) -> N.

    includes(Enumeral_1) -> true;
    ...
    includes(Enumeral_N) -> true;
    includes(X) when atom(X) -> false.

    members() -> [Enumeral_1, ..., Enumeral_N].

Here are some macro definitions in M4 that do the job:

define(`def_from_int',
`define(`counter',eval(counter+1))from_integer(counter) -> $1`'ifelse($#,1, `.
', `;
def_from_int(shift($@))')')dnl
define(`def_to_int',
`define(`counter', eval(counter+1))to_integer($1) -> counter`'ifelse($#,1, `.
', `;
def_to_int(shift($@))')')dnl
define(`def_inc', `includes($1) -> true;
ifelse($#,1, `includes(X) when atom(X) -> false.
', `def_inc(shift($@))')')dnl
define(`define_enumeration',
`-module($1).
-export([size/0,from_integer/1,to_integer/1,includes/1,members/0]).

size() -> eval($#-1).

define(`counter', 0)def_from_int(shift($@))
define(`counter', 0)def_to_int(shift($@))
def_inc(shift($@))
members() -> [shift($@)].
')dnl

Put that in file enum.m4

Put this example in every.erl.m4:

    define_enumeration(every, tom,dick,harry)

(note no square brackets or trailing dot). Run it like this:
    
    m4 enum.m4 every.erl.m4 >every.erl

And what you get is

    -module(every).
    -export([size/0,from_integer/1,to_integer/1,includes/1,members/0]).

    size() -> 3.

    from_integer(1) -> tom;
    from_integer(2) -> dick;
    from_integer(3) -> harry.

    to_integer(tom) -> 1;
    to_integer(dick) -> 2;
    to_integer(harry) -> 3.

    includes(tom) -> true;
    includes(dick) -> true;
    includes(harry) -> true;
    includes(X) when atom(X) -> false.

    members() -> [tom,dick,harry].

I chose M4 as the simplest and quickest way to do the job.
Of course you could do this in Erlang.




More information about the erlang-questions mailing list