how to efficiently build erlang lists in natural order? - erlang

In the Programming Erlang book, there is some example pseudo code that shows a pattern for efficiently adding elements to the head of a list:
some_function([H|T], ..., Result, ...) ->
H1 = ... H ...,
some_function(T, ..., [H1|Result], ...);
some_function([H|T], ..., Result, ...) ->
{..., Result, ...}.
I'm still getting used to functional programming so the above example is a little too abstract for me to understand at the moment.
I think it will be easier to understand if there is a concrete implementation of the pattern that I could dissect.
Question: Is there a simple concrete implementation of this pattern that someone can provide?

Let's say that we want a function which behaves a like the uniq command.
The function takes a list of elements and returns a list with all consecutive occurrences of an element substituted with a single occurrence of that element.
One of the possible approaches is presented below:
uniq(L) ->
uniq(L, []).
uniq([], Acc) ->
lists:reverse(Acc);
uniq([H, H | T], Acc) ->
uniq([H | T], Acc);
uniq([H | T], Acc) ->
uniq(T, [H | Acc]).
We build up an accumulator, by inserting new elements at the head of the Acc list (cheapest insertion cost) and once we're done, we reverse the whole list to get the initial order of elements back.
We "visit" some of the elements of the initial list twice, but the total cost is still linear, i.e. only dependent on the number of elements of the initial list.

This takes a factorized list, i.e.
[[],[2],[3],[2,2],[5],[2,3],[7],[2,2,2],etc...]
and removes all the primes.
remove_primes([HD|TL], Results) ->
case length(HD) of
0 -> % You're at 1
remove_primes (TL , Results);
1 -> % Its a prime, remove it, and keep going
remove_primes( TL , Results) ;
_ -> % its not prime, leave it in and keep going.
remove_primes(TL, [ HD | Results])
end;
remove_primes([], Result) ->
{Result}.
The structure Joe Armstrong was alluding too, is the standard structure of walking a list and applying a function to each element on the list. In this case, I desired to treat each element differently depending on its contents.
In practice, it is much easier to to use maps, filters and such, so I believe you will see that much more often - but as you seem to know, understanding the basics is vital to becoming a proficient functional programmer.
In hopes centralize information pertaining to 'building lists in natural order', does anyone know why pattern matching at the function level, works, 'but unpacking' a variable does not? (compare this)(it does not work)
remove_primes(Factorized_List, Results) ->
[HD|TL] = Factorized_List, % unpack the list <-------------
case length(HD) of
0 -> % You're at 1
remove_primes (TL , Results);
1 -> % Its a prime, remove it, and keep going
remove_primes( TL , Results) ;
_ -> % its not prime, leave it in and keep going.
remove_primes(TL, [HD|Results])
end;
remove_primes([], Result) ->
{Result}.
I believe this leads to more readable code, but it does not seem to work.
-rC

Here is the only way I can get your pattern to execute:
some_func([H|T], 4, Result, 4) ->
H1 = H * 2,
some_func(T, 3, [H1|Result], 4);
some_func([H|T], 3, Result, _) ->
{H, Result, T}.
--output:--
25> a:some_func([1, 2, 3], 4, [], 4).
{2,[2],[3]}
...which does nothing useful.
The pattern in the pseudo code makes no sense to me, so I'll join you in your confusion.
Here is another attempt:
some_func([H|T], [_|T2], Result, Y) ->
H1 = H * Y,
some_func(T, T2, [H1|Result], Y);
some_func([H|T], [], Result, _) ->
{H, Result, T}.
--output:--
34> a:some_func([1, 2, 3, 4], [one, two, three], [], 2).
{4,[6,4,2],[]}

Related

Erlang: serial implementation of accumulator

I am trying to create a method that takes an associative and commutative operator, as well a list of values, and then returns the answer by applying an operator to the values in the list.
The following two examples represent what the input/output are supposed to look like.
Example 1
Input: sum(fun(A,B) -> A+B end, [2,6,7,10,12]).
Output: 37
Example 2
Input: sum(fun (A,B) -> A++B end , ["C", "D", "E"]).
Output: "CDE"
This is the code I am working with so far.
-module(tester).
-compile(export_all).
sum(Func, Data, Acc) ->
lists:foldr(Func, Acc, Data).
This code produces the correct result, however, there are two problems I am trying to figure out how to approach answering.
(1) In order for this code to work, it requires an empty list to be included at the end of the command line statements. In other words, if I enter the input above (as in the examples), it will err out, because I did not write it in the following way:
12> tester:sum(fun(X, Acc) -> X+Acc end, [2,6,7,10,12], 0).
How would I implement this without an empty list as in the examples above and get the same result?
(2) Also, how would the code be implemented without the list function, or in an even more serial way?
How would I implement this without an empty list as in the examples above and get the same result?
Assuming the list always has one element (you can't really do it without this assumption), you can extract the first element from the list and pass that as the initial accumulator. You'll need to switch to foldl to do this efficiently. (With foldr you'll essentially need to make a copy of the list to drop the last element.)
sum(Func, [X | Xs]) ->
lists:foldl(fun (A, B) -> Func(B, A) end, X, Xs).
1> a:sum(fun(A,B) -> A+B end, [2,6,7,10,12]).
37
2> a:sum(fun (A,B) -> A++B end , ["C", "D", "E"]).
"CDE"
Also, how would the code be implemented without the list function, or in an even more serial way?
Here's a simple implementation using recursion and pattern matching:
sum2(Func, [X | Xs]) ->
sum2(Func, Xs, X).
sum2(Func, [], Acc) ->
Acc;
sum2(Func, [X | Xs], Acc) ->
sum2(Func, Xs, Func(Acc, X)).
We define two versions of the function. The first one extracts the head and uses that as the initial accumulator. The second one, with arity 3, does essentially what the fold functions in lists do.
After working on this for a while, this was my solution. I've left some comments about the general idea of what I did, but there's a lot more to be said.
-module(erlang2).
-compile(export_all).
-export([reduce/2]).
reduce(Func, List) ->
reduce(root, Func, List).
%When done send results to Parent
reduce(Parent, _, [A]) ->
%send to parent
Parent ! { self(), A};
%I tried this at first to take care of one el in list, but it didn't work
%length ([]) ->
% Parent ! {self(), A};
%get contents of list, apply function and store in Parent
reduce(Parent, Func, List) ->
{ Left, Right } = lists:split(trunc(length(List)/2), List),
Me = self(),
%io:format("Splitting in two~n"),
Pl = spawn(fun() -> reduce(Me, Func, Left) end),
Pr = spawn(fun() -> reduce(Me, Func, Right) end),
%merge results in parent and call Func on final left and right halves
combine(Parent, Func,[Pl, Pr]).
%merge pl and pl and combine in parent
combine(Parent, Func, [Pl, Pr]) ->
%wait for processes to complete (using receive) and then send to Parent
receive
{ Pl, Sorted } -> combine(Parent, Func, Pr, Sorted);
{ Pr, Sorted } -> combine(Parent, Func, Pl, Sorted)
end.
combine(Parent, Func, P, List) ->
%wait and store in results and then call ! to send
receive
{ P, Sorted } ->
Results = Func(Sorted, List),
case Parent of
root ->
Results;
%send results to parent
_ -> Parent ! {self(), Results}
end
end.

Understanding what this Erlang Code is?

Not at all familiar with Erlang, but am trying to interpret what this code does?
Below is my understanding about the code. Any help will be useful.
I am looking at the tutorials but the passing values are confusing in this case.
example- convert_list_to_k([{Name, {l, Weight}} | Rest]) //{1,Weight} <- This one
And how is the value returned in convert_list_to_k?
let's say for this function block
convert_list_to_k([{Name, {l, Weight}} | Rest]) ->
Converted_Object = {Name, {k, Weight / 0.45359237}},
[Converted_Object | convert_list_to_k(Rest)];
convert_list_to_k([Object | Rest]) ->
[Object | convert_list_to_k(Rest)];
convert_list_to_k([]) ->
[].
Below is the code with explanations.
-module(erlang_program).
-export([format_weight/1]).
in the above export the /1 represents it's going to receive an attribute(I don't know which attribute)
format_weight(List_of_objects) ->
Converted_List = convert_list_to_k(List_of_objects),
print_weight(Converted_List),
{Max_object, Min_object} = find_max_and_min(Converted_List),
print_max_and_min(Max_object, Min_object).
Kind of main function, which will import convert_list_to_k, print_weight(Converted_List),find_max_and_min(Converted_List) and print_max_and_min(Max_object, Min_object).
According to my understanding it's doing the following things:
Converts a list of object to some format
Prints the converted list
Find the Max and Min, and place it in Object Max and Min
Prints the Max and Min Object
I am getting confused by the way [{Name, {l, Weight}} | Rest] is passed
convert_list_to_k([{Name, {l, Weight}} | Rest]) ->
Converted_Object = {Name, {k, Weight / 0.45359237}},
[Converted_Object | convert_list_to_k(Rest)];
convert_list_to_k([Object | Rest]) ->
[Object | convert_list_to_k(Rest)];
convert_list_to_k([]) ->
[].
print_weight([{Name, {k, Weight}} | Rest]) ->
io:format("~-15w ~w c~n", [Name, Weight]),
print_weight(Rest);
print_weight([]) ->
ok.
find_max_and_min([Object | Rest]) ->
find_max_and_min(Rest, Object, Object).
find_max_and_min([{Name, {k, Weight}} | Rest],
{Max_Name, {k, Max_Weight}},
{Min_Name, {k, Min_Weight}}) ->
if
Weight > Max_Weight ->
Max_Object = {Name, {k, Weight}};
true ->
Max_Object = {Max_Name, {k, Max_Weight}}
end,
if
Weight < Min_Weight ->
Min_Object = {Name, {k, Weight}};
true ->
Min_Object = {Min_Name, {k, Min_Weight}}
end,
find_max_and_min(Rest, Max_Object, Min_Object);
find_max_and_min([], Max_Object, Min_Object) ->
{Max_Object, Min_Object}.
print_max_and_min({Max_name, {k, Max_object}}, {Min_name, {k, Min_object}}) ->
io:format("Max weight was ~w c in ~w~n", [Max_object, Max_name]),
io:format("Min weight was ~w c in ~w~n", [Min_object, Min_name]).
Don't worry that this code is a bit confusing. It is somewhat unidiomatic. We'll address that in a moment...
Before style, look at this first function, convert_list_to_k/1. It is selectively converting objects from a form marked with l to a form marked with k.
How is it selecting? It is matching on the shape and value of the first element of the list passed to it as an argument. If it receives a value with an l type value inside like {Name, {l, Weight}} then the first clause is selected and run, which converts the {l, Weight} part to a {k, Weight} value -- I assume here this is "l" for "pounds" and "k" for "kilograms".
This function is doing depth recursion which is not usually a good fit for this particular case, because Erlang (and most functional languages) have an optimization for tail recursion.
foo([Thing | Things]) ->
NewThing = change(Thing),
[NewThing | foo(Things)];
foo([]) ->
[].
This is basically what the function is doing. This means that for whatever size the list is, a new layer of the call stack has to be added because the original list in the first clause cannot be returned without remembering every intermediate value. This will not work on arbitrarily long lists without significant memory overhead and is generally not how things work.
Imagine in memory seeing this:
foo([change(Thing1) | foo([change(Thing2) | foo([change(Thing3) | ...]]])
Not very tidy. Sometimes it is the right thing to do, but not in the general case of iterating over a list.
A tail recursive version would look like this:
foo(Things) ->
foo(Things, []).
foo([Thing | Things], Accumulator) ->
NewThing = change(Thing),
foo(Things, [NewThing | Accumulator]);
foo([], Accumulator) ->
lists:reverse(Accumulator).
This version runs in constant space and is the more idiomatic form of explicit recursion.
So what about all that matching stuff? Well, let's say I wanted to print a value in kilograms every time, but some of my values are in pounds and some are in kilos. I could wrap the raw number values in a tuple and use an atom to tag the values so I know what they mean. For example, a tuple like {pounds, X} would mean I have a number, X, and it is in pounds, or a tuple {kilos, X} which would mean X is kilos. Both are still weight.
So how would my function look?
print_weight({kilos, X}) ->
io:format("Weight is ~wkgs~n", [X]);
print_weight({pounds, X}) ->
Kilos = X / 0.45359237,
io:format("Weight is ~wkgs~n", [Kilos]).
So this function works fine as long as it is passed either kind of tuple.
How about a list of these? We could do explicit recursion like above:
print_weights([{kilos, X} | Rest]) ->
ok = io:format("Weight is ~wkgs~n", [X]),
print_weights(Rest);
print_weight([{pounds, X} | Rest]) ->
Kilos = X / 0.45359237,
ok = io:format("Weight is ~wkgs~n", [Kilos]),
print_weights(Rest);
print_weights([]) ->
ok.
So this handles a list of values like above. But we don't really need to write all that, do we? We already had a function called print_weight/1, and it already knows how to do the matching. What we could do instead is more simply define print_weights/1 as a function that uses a list operation:
print_weights(List) ->
lists:foreach(fun print_weight/1, List).
See, we usually don't do explicit recursion when we can help it. The reason is that in the simple case we already have higher-order functions made to simplify simple iteration over lists. In the case where we want a side effect and don't care about the return value, like printing the weights as above, we use lists:foreach/2.
Going back to the "change" example above, if we already know that we want to perform change/1 on each value, but return the same map back intact, it makes more sense to either use a list comprehension or lists:map/2.
A list comprehension is a special syntax over a map, which can also include guards. The simple case of mapping a function over every value in a list and returning that list looks like this:
ChangedThings = [change(Thing) || Thing <- Things]
A map looks almost exactly the way lists:foreach/2 did above:
ChangedThings = lists:map(fun change/1, Things)
Now, going back to your original example... maybe we want to ensure a specific value type. So we could write a simple function that does only that:
ensure_metric({Name, {l, Pounds}}) ->
Kilos = Pounds / 0.45359237,
{Name, {k, Kilos}};
ensure_metric(Value = {_, {k, _}}) ->
Value.
That's all we need. What is happening above is that any tuple of the form {Foo, {l, Bar}} matches the first clause and gets converted by the operation in that clause and then repacked to a {Foo, {k, Baz} form, and any tuple of the form {Foo, {k, Bar}} matches the second but is passed along without being changed. We can now simply map that function over a list:
convert_list_to_k(List) ->
lists:map(fun ensure_metric/1, List).
Much easier to reason about just one function at a time!
The min/max function is a bit insane. We would not want to write an if unless we had a fully bounded mathematical case. For example:
if
X > Y -> option1();
X =:= Y -> option2();
X == Y -> option3();
X < Y -> option4()
end,
This is four tests in a single clause. Occasionally using an if makes sense for that. More often, though, you wind up with what you had above, where a simple comparison happens. In that case a case is much more expressive:
case X > Y ->
true -> do_something();
false -> something_else()
end,
BUT! Maybe what we really want in a min/max function is to just operate over guards and avoid writing some complex body logic. Here is one that operates over a simple list of numbers, a slight change would make it fit the data type you are dealing with (those tuples):
min_max([Number | Numbers]) ->
min_max(Numbers, Number, Number).
min_max([N | Ns], Min, Max) when N < Min ->
min_max(Ns, N, Max);
min_max([N | Ns], Min, Max) when N > Max ->
min_max(Ns, Min, N);
min_max([_ | Ns], Min, Max) ->
min_max(Ns, Min, Max);
min_max([], Min, Max) ->
{Min, Max}.
Not a whole lot of cheetah flips are needed in procedural logic here.
Erlang is so boringly simple and tiny as a language that once the needlessness of most procedural logic sinks in you just suddenly "get new eyes". A few related Q/As with background information may be helpful on your journey:
Erlang Recursive end loop
How does the recursive call work in this erlang function?
Explanation of lists:fold function
Function chaining in Erlang

Counting down from N to 1

I'm trying to create a list and print it out, counting down from N to 1. This is my attempt:
%% Create a list counting down from N to 1 %%
-module(list).
-export([create_list/1]).
create_list(N) when length(N)<hd(N) ->
lists:append([N],lists:last([N])-1),
create_list(lists:last([N])-1);
create_list(N) ->
N.
This works when N is 1, but otherwise I get this error:
172> list:create_list([2]).
** exception error: an error occurred when evaluating an arithmetic expression
in function list:create_list/1 (list.erl, line 6)
Any help would be appreciated.
You should generally avoid using append or ++, which is the same thing, when building lists. They both add elements to the end of a list which entails making a copy of the list every time. Sometimes it is practical but it is always faster to work at the front of the list.
It is a bit unclear in which order you wanted the list so here are two alternatives:
create_up(N) when N>=1 -> create_up(1, N). %Create the list
create_up(N, N) -> [N];
create_up(I, N) ->
[I|create_up(I+1, N)].
create_down(N) when N>1 -> %Add guard test for safety
[N|create_down(N-1)];
create_down(1) -> [1].
Neither of these are tail-recursive. While tail-recursion is nice it doesn't always give as much as you would think, especially when you need to call a reverse to get the list in the right order. See Erlang myths for more information.
The error is lists:last([N])-1. Since N is an array as your input, lists:last([N]) will return N itself. Not a number you expect. And if you see the warning when compiling your code, there is another bug: lists:append will not append the element into N itself, but in the return value. In functional programming, the value of a variable cannot be changed.
Here's my implementation:
create_list(N) ->
create_list_iter(N, []).
create_list_iter(N, Acc) ->
case N > 0 of
true -> NewAcc = lists:append(Acc, [N]),
create_list_iter(N-1, NewAcc);
false -> Acc
end.
If I correctly understand your question, here is what you'll need
create_list(N) when N > 0 ->
create_list(N, []).
create_list(1, Acc) ->
lists:reverse([1 | Acc]);
create_list(N, Acc) ->
create_list(N - 1, [N | Acc]).
If you work with lists, I'd suggest you to use tail recursion and lists construction syntax.
Also, to simplify your code - try to use pattern matching in function declarations, instead of case expressions
P.S.
The other, perhaps, most simple solution is:
create_list(N) when N > 0 ->
lists:reverse(lists:seq(1,N)).

Overuse of guards in Erlang?

I have the following function that takes a number like 5 and creates a list of all the numbers from 1 to that number so create(5). returns [1,2,3,4,5].
I have over used guards I think and was wondering if there is a better way to write the following:
create(N) ->
create(1, N).
create(N,M) when N =:= M ->
[N];
create(N,M) when N < M ->
[N] ++ create(N + 1, M).
The guard for N < M can be useful. In general, you don't need a guard for equality; you can use pattern-matching.
create(N) -> create(1, N).
create(M, M) -> [M];
create(N, M) when N < M -> [N | create(N + 1, M)].
You also generally want to write functions so they are tail-recursive, in which the general idiom is to write to the head and then reverse at the end.
create(N) -> create(1, N, []).
create(M, M, Acc) -> lists:reverse([M | Acc]);
create(N, M, Acc) when N < M -> create(N + 1, M, [N | Acc]).
(Of course, with this specific example, you can alternatively build the results in the reverse order going down to 1 instead of up to M, which would make the lists:reverse call unnecessary.)
If create/2 (or create/3) is not exported and you put an appropriate guard on create/1, the extra N < M guard might be overkill. I generally only check on the exported functions and trust my own internal functions.
create(N,N) -> [N];
create(N,M) -> [N|create(N + 1, M)]. % Don't use ++ to prefix a single element.
This isn't quite the same (you could supply -5), but it behaves the same if you supply meaningful inputs. I wouldn't bother with the extra check anyway, since the process will crash very quickly either way.
BTW, you have a recursion depth problem with the code as-is. This will fix it:
create(N) ->
create(1, N, []).
create(N, N, Acc) -> [N|Acc];
create(N, M, Acc) -> create(N, M - 1, [M|Acc]).
I don't really think you have over used guards. There are two cases:
The first is the explicit equality test in the first clause of create/2
create(N, M) when N =:= M -> [M];
Some have suggested transforming this to use pattern matching like
create(N, N) -> [N];
In this case it makes no difference as the compiler internally transforms the pattern matching version to what you have written. You can safely pick which version you think feels best in each case.
In the second case you need some form of sanity check that the value of the argument in the range you expect it to be. Doing in every loop is unnecessary and I would move it to an equivalent test in create/1:
create(M) when M > 1 -> create(1, M).
If you want to use an accumulator I would personally use the count version as it saves reversing the list at the end. If the list is not long I think the difference is very small and you can pick the version which feels most clear to you. Anyway, it is very easy to change later if you find it to be critical.

right rotate a List in Erlang

I am getting myself familiar to Sequential Erlang (and the functional programming thinking) now. So I want to implement the following two functionality without the help of BIF. One is left_rotate (which I have come up with the solution) and the other is right_rotate (which I am asking here)
-export(leftrotate/1, rightrotate/1).
%%(1) left rotate a lits
leftrotate(List, 0) ->
List;
leftrotate([Head | Tail], Times) ->
List = append(Tail, Head),
leftrotate(List, Times -1).
append([], Elem)->
[Elem];
append([H|T], Elem) ->
[H | append(T, Elem)].
%%right rotate a list, how?
%%
I don't want to use BIF in this exercise. How can I achieve the right rotation?
A related question and slightly more important question. How can I know one of my implementation is efficient or not (i.e., avoid unnecessary recursion if I implement the same thing with the help of a BIF, and etc.)
I think BIF is built to provide some functions to improve efficiency that functional programming is not good at (or if we do them in a 'functional way', the performance is not optimal).
The efficiency problem you mention has nothing to do with excessive recursion (function calls are cheap), and everything to do with walking and rebuilding the list. Every time you add something to the end of a list you have to walk and copy the entire list, as is obvious from your implementation of append. So, to rotate a list N steps requires us to copy the entire list out N times. We can use lists:split (as seen in one of the other answers) to do the entire rotate in one step, but what if we don't know in advance how many steps we need to rotate?
A list really isn't the ideal data structure for this task. Lets say that instead we use a pair of lists, one for the head and one for the tail, then we can rotate easily by moving elements from one list to the other.
So, carefully avoiding calling anything from the standard library, we have:
rotate_right(List, N) ->
to_list(n_times(N, fun rotate_right/1, from_list(List))).
rotate_left(List, N) ->
to_list(n_times(N, fun rotate_left/1, from_list(List))).
from_list(Lst) ->
{Lst, []}.
to_list({Left, Right}) ->
Left ++ reverse(Right).
n_times(0, _, X) -> X;
n_times(N, F, X) -> n_times(N - 1, F, F(X)).
rotate_right({[], []}) ->
{[], []};
rotate_right({[H|T], Right}) ->
{T, [H|Right]};
rotate_right({[], Right}) ->
rotate_right({reverse(Right), []}).
rotate_left({[], []}) ->
{[], []};
rotate_left({Left, [H|T]}) ->
{[H|Left], T};
rotate_left({Left, []}) ->
rotate_left({[], reverse(Left)}).
reverse(Lst) ->
reverse(Lst, []).
reverse([], Acc) ->
Acc;
reverse([H|T], Acc) ->
reverse(T, [H|Acc]).
The module queue provides a data structure something like this. I've written this without reference to that though, so theirs is probably more clever.
First, your implementation is a bit buggy (try it with the empty list...)
Second, I would suggest you something like:
-module(foo).
-export([left/2, right/2]).
left(List, Times) ->
left(List, Times, []).
left([], Times, Acc) when Times > 0 ->
left(reverse(Acc), Times, []);
left(List, 0, Acc) ->
List ++ reverse(Acc);
left([H|T], Times, Acc) ->
left(T, Times-1, [H|Acc]).
right(List, Times) ->
reverse(foo:left(reverse(List), Times)).
reverse(List) ->
reverse(List, []).
reverse([], Acc) ->
Acc;
reverse([H|T], Acc) ->
reverse(T, [H|Acc]).
Third, for benchmarking your functions, you can do something like:
test(Params) ->
{Time1, _} = timer:tc(?MODULE, function1, Params),
{Time2, _} = timer:tc(?MODULE, function2, Params),
{{solution1, Time1}, {solution2, Time2}}.
I didn't test the code, so look at it critically, just get the idea.
Moreover, you might want to implement your own "reverse" function. It will be trivial by using tail recursion. Why not to try?
If you're trying to think in functional terms then perhaps consider implementing right rotate in terms of your left rotate:
rightrotate( List, 0 ) ->
List;
rightrotate( List, Times ) ->
lists:reverse( leftrotate( lists:reverse( List ), Times ) ).
Not saying this is the best idea or anything :)
Your implementation will not be efficient since the list is not the correct representation to use if you need to change item order, as in a rotation. (Imagine a round-robin scheduler with many thousands of jobs, taking the front job and placing it at the end when done.)
So we're actually just asking ourself what would be the way with least overhead to do this on lists anyway. But then what qualifies as overhead that we want to get rid of? One can often save a bit of computation by consing (allocating) more objects, or the other way around. One can also often have a larger than needed live-set during the computation and save allocation that way.
first_last([First|Tail]) ->
put_last(First, Tail).
put_last(Item, []) ->
[Item];
put_last(Item, [H|Tl]) ->
[H|put_last(Item,Tl)].
Ignoring corner cases with empty lists and such; The above code would cons the final resulting list directly. Very little garbage allocated. The final list is built as the stack unwinds. The cost is that we need more memory for the entire input list and the list in construction during this operation, but it is a short transient thing. My damage from Java and Lisp makes me reach for optimizing down excess consing, but in Erlang you dont risk that global full GC that kills every dream of real time properties. Anyway, I like the above approach generally.
last_first(List) ->
last_first(List, []).
last_first([Last], Rev) ->
[Last|lists:reverse(Rev)];
last_first([H|Tl], Rev) ->
last_first(Tl, [H|Rev]).
This approach uses a temporary list called Rev that is disposed of after we have passed it to lists:reverse/1 (it calls the BIF lists:reverse/2, but it is not doing anything interesting). By creating this temporary reversed list, we avoid having to traverse the list two times. Once for building a list containing everything but the last item, and one more time to get the last item.
One quick comment to your code. I would change the name of the function you call append. In a functional context append usually means adding a new list to the end of a list, not just one element. No sense in adding confusion.
As mentioned lists:split is not a BIF, it is a library function written in erlang. What a BIF really is is not properly defined.
The split or split like solutions look quite nice. As someone has already pointed out a list is not really the best data structure for this type of operation. Depends of course on what you are using it for.
Left:
lrl([], _N) ->
[];
lrl(List, N) ->
lrl2(List, List, [], 0, N).
% no more rotation needed, return head + rotated list reversed
lrl2(_List, Head, Tail, _Len, 0) ->
Head ++ lists:reverse(Tail);
% list is apparenly shorter than N, start again with N rem Len
lrl2(List, [], _Tail, Len, N) ->
lrl2(List, List, [], 0, N rem Len);
% rotate one
lrl2(List, [H|Head], Tail, Len, N) ->
lrl2(List, Head, [H|Tail], Len+1, N-1).
Right:
lrr([], _N) ->
[];
lrr(List, N) ->
L = erlang:length(List),
R = N rem L, % check if rotation is more than length
{H, T} = lists:split(L - R, List), % cut off the tail of the list
T ++ H. % swap tail and head

Resources