[erlang-questions] Generating readable unique IDs for use outside erlang

Ulf Wiger <>
Thu Feb 10 17:01:23 CET 2011


On 10 Feb 2011, at 15:34, Dave Challis wrote:

> Is there a good (and fast) way of generating a unique id for use outside Erlang?


Depending on your needs, it could be useful to provide a mapping between
an internal id and an external, reasonably memorable, one.

This code is from a blog example in ErlHive
(http://erlhive.svn.sourceforge.net/viewvc/erlhive/trunk/lib/erlhive/examples/blog/src/flexiblog.erl?revision=69&view=markup)

The trick for generating a unique Id in this case was to rely on the Erlhive 'stream' data type:

new_blog(Properties) ->
    Caller = erlhive.user:auth(),
    B_props = blog_props(Properties),
    N = erlhive.user:append([blogs, Caller], B_props),
    Key = [blogs, Caller, N],

then providing conversion functions to/from external presentation:

%%% @spec (item()) -> string()
%%% @doc Converts an internal blog, article or comment identifier
%%% to an external representation.
%%%
id_to_string([blogs,U,I]) when is_binary(U), is_integer(I) ->
    "blogs/" ++ .lists:concat([b2l(U), "/", i2l(I)]);
id_to_string([ba,U,I,J]) when is_binary(U), is_integer(I), is_integer(J) ->
    "ba/" ++ blog_item_serial(U,I,J);
id_to_string([bc,U,I,J]) when is_binary(U), is_integer(I), is_integer(J) ->
    "bc/" ++ blog_item_serial(U,I,J).


blog_item_serial(U, I, J) ->
    .lists:concat([b2l(U), "/", i2l(I), "/", i2l(J)]).

b2l(B) ->
    binary_to_list(B).
i2l(I) ->
    integer_to_list(I).

%%% @spec (string()) -> item()
%%% @doc Converts an external string representation to an internal
%%% blog, article or comment identifier.
%%%
string_to_id("blogs/" ++ BStr) ->
    {UStr, I} = one_int(BStr),
    [blogs, list_to_binary(UStr), I];
string_to_id("ba/" ++ BIStr) ->
    {UStr, I, J} = two_ints(BIStr),
    [ba, list_to_binary(UStr), I, J];
string_to_id("bc/" ++ BIStr) ->
    {UStr, I, J} = two_ints(BIStr),
    [bc, list_to_binary(UStr), I, J].

one_int(Str) ->
    {RevS, I} = pick(.lists:reverse(Str), []),
    {.lists:reverse(RevS), I}.

two_ints(Str) ->
    {Rest1, J} = pick(.lists:reverse(Str), []),
    {Rest2, I} = pick(Rest1, []),
    {.lists:reverse(Rest2), I, J}.

pick("/" ++ Rest, Acc) ->
    {Rest, list_to_integer(Acc)};
pick([H|T], Acc) when H >= $0, H =< $9 ->
    pick(T, [H|Acc]).


Otherwise, I too like the {node(), now()} version.

BR,
Ulf


> 
> The best method I can find for generating a unique id is to use:
> {node(), now()}
> 
> Which generates something like:
> {,{1297,347375,276224}}
> 
> This works great, and is what I use within erlang.
> 
> However, it looks a bit meaningless is likely to confuse users of the non-erlang application that uses it - is there a nice way to turn that into an integer, or series of integers instead?
> 
> E.g. turning the above into:
> 3473290872_1297_347375_276224
> (or ideally a single integer)
> 
> would be fine, but I'm not sure how to get an integer from a term.
> 
> Chances are I'll be generating hundreds of thousands to several million of these, so I'm also a bit concerned about efficiency - turning the {node(), now()} tuple into a string would no doubt take up more memory (and some processing time).
> 
> Any suggestions on this?
> 
> -- 
> Dave Challis
> 
> 
> ________________________________________________________________
> erlang-questions (at) erlang.org mailing list.
> See http://www.erlang.org/faq.html
> To unsubscribe; mailto:
> 

Ulf Wiger, CTO, Erlang Solutions, Ltd.
http://erlang-solutions.com





More information about the erlang-questions mailing list