[erlang-questions] Erlang newbie - quick critique?
Thu Sep 7 09:34:21 CEST 2006
On Thu, Sep 07, 2006 at 04:30:35PM +1200, Liam Clarke wrote:
> Hi all,
> Rather new to the FP paradigm (painful learning curve with an attempt
> at Common Lisp) so I just thought I'd run my first attempts at a
> recursive Erlang function past you.
> I'm not near an Erlang interpreter at the moment, unfortunately, so I
> can't test the code, I'm worried about one bit, which I'll highlight.
> I'm trying to replicate the string.join() method of Python i.e.,
> ":".join(["a", "b", "c"]) resulting in "a:b:c"
> This is what I've drawn up on paper -
You may have forgotten the corner case of:
my_join(, _Delimiter) ->
or maybe it should be an error case?
In that case you will get a function clause error for
my_join(, ":"), which maybe is what you desire.
> my_join([H|T] Delimiter) ->
> myjoin(T, Delimiter, [H])).
% To (probably) not get "a:b:c:" as a result:
my_join([H], Delimiter, Acc) ->
> my_join([H|T], Delimiter, Acc) ->
> myjoin(T, Delimiter, lists:append([Acc, Delimiter, H]) ).
> my_join(, Delimiter, Acc) ->
> Usage: my_join(["a", "b", "c"], ":")
> What I'm concerned about is the [H] and the lists:append call with the
> arguments being inserted into two square brackets to make a new list.
Since the documentation of lists:append/1 says it takes a list
of lists to append, it should work.
> Would that work? It's a Python thing, or do I need to use a function
> to make it a list?
NoNo, that is how you create lists in erlang, just as simple as
What is not good in your example is that you call lists:append/1
in a loop over the lists to join, and since lists:append has to
append to an increasing accumulator list you get a function that is
quadratic ( O(n*n) ) for execution time, and that is mostly
a bad thing except for short lists.
The Erlang way to do it would probably be either:
%my_join(, _Delimiter) ->
my_join([H], _Delimiter) ->
my_join([H|T], Delimiter) ->
H ++ (Delimiter ++ my_join(T, Delimiter)).
a forward list building variant which will do lists:append/2 (i.e ++)
onto only the individual sublists, and therefore process
all elements only once, or:
my_join(ListOfLists, Delimiter) ->
my_join(ListOfLists, Delimiter, ).
%my_join(, _Delimiter, R) ->
my_join([H], _Delimiter, R) ->
my_join([H|T], Delimiter, R) ->
my_join(T, Delimiter, lists:reverse(Delimiter, lists:reverse(H, T))).
a variant that build all lists backwards, that is on the list
head therefore also process every element only once (except for
the Delimiter elements, just like the first variant), and then reverses
the result list at the end. It uses lists:reverse/2 that reverses the
first argument and appends the second in one swift operation.
A sub-variant would be to reverse Delimiter at the start, use
DelimiterR in the loop and replace the first lists:reverse in the loop
with a ++.
If you want to know which one is the fastes you will have to benchmark.
Which one is the shortest is obvious.
Which one is easies to read is continously debated.
Note: I have not tested them either...
Note2: other people have other Erlang ways...
> I've decided to start small for now - I intend to use Erlang to write
> an MSN client as I think the asynchrous nature of Erlang (and I love
> the sockets returning messages) suits the problem perfectly. I had
> started in Python, but have hit a bunch of fiddliness with asynchrous
> sockets, so thought I'd give Erlang a go.
> In designing the actual architecture of an Erlang system, can anyone
> recommend some best practises? I'm working on the message interfaces
> between the socket handling process and it's controller at the moment.
> Liam Clarke
> erlang-questions mailing list
/ Raimo Niskanen, Erlang/OTP, Ericsson AB
More information about the erlang-questions