Tag Archives: Erlang Thursday

Erlang Thursday – lists:flatten/1

Today’s Erlang Thursday function is lists:flatten/1.

lists:flatten/1 flattens out an arbitrarily deep list of Erlang terms, into a “flattened” list.

1
2
3
4
5
6
7
8
lists:flatten([]).
% []
lists:flatten([a, b, c]).
% [a,b,c]
lists:flatten([a, b, [1, [x, y], 3], c]).
% [a,b,1,x,y,3,c]
lists:flatten([a, b, [1, [x, {some, tuple}], 3], c]).   
% [a,b,1,x,{some,tuple},3,c]

Be warned though, it flattens out all lists, as seen here

1
2
lists:flatten([a, "foo", b]).   
% [a,102,111,111,b]

You get the above lists with numbers in it, because under the covers, a string is just a list of integers, so you get the ASCII character codes for the letters f and o in "foo".

If you want the string to “remain”, you need to use the string as a binary type like this:

1
2
lists:flatten([a, <<"foo">>, b]).                      
% [a,<<"foo">>,b]

And as a bonus, there is also a lists:flatten/2, that takes a list to flatten, and another argument tail, which is the value to append to the newly flattened list.

1
2
lists:flatten([a, [1, [b, [2]]]], [x, y, z]).
% [a,1,b,2,x,y,z]

–Proctor

Erlang Thursday – lists:max/1

Today’s Erlang function is lists:max/1.

lists:max/1 takes one argument, a list of at least one term, and returns the item that has the greatest value when compared to the other items in the list. The list can be composed of any Erlang term:

1
2
3
4
5
6
lists:max([1, 39, 7, 63, 27, 52, 16]).
% 63
lists:max([q, w, a, r, c, f, m, b]).     
% w
lists:max([[1, 2, 3], [1, 2, 4]]).
% [1,2,4]

Erlang has a distinct order between the different types of terms,

number < atom < reference < fun < port < pid < tuple < list < bit string

allowing for the list passed to lists:max/1 to be comprised of disparate types.

1
2
3
4
lists:max([1, 2, 3, 4, a]).        
% a
lists:max([1, a, [foo, bar], {baz}]).
% [foo,bar]

And because a string in Erlang is just a list of numbers under the covers, we can even compare strings.

1
2
lists:max(["foo", "bar", "baz", "snafu"]).
"snafu"

If you pass an empty list to lists:max/1 a no function clause matching error will be raised, since it expects the list to be at least composed of one term.

1
2
lists:max([]).
** exception error: no function clause matching lists:max([]) (lists.erl, line 326)

What are some of your favorite Erlang functions, or even just ones you would like to see a future Erlang Thursday post about?

And don't forget to check out the last Tuesday's Ruby Tuesday on Enumerable#max, if you would like a comparison between Erlang's max function and Ruby's max method.

--Proctor

Erlang Thursday – lists:seq

My goal of these Erlang Thursday’s for the next while will be to show off the “corresponding” functions in Erlang for the Ruby methods I highlight on Tuesday. I am hoping that by having these Erlang Thursday line up with the Ruby Tuesday for the week, that I can make Erlang be less foreign and intimidating by establishing a common thread of discussion. I would love to know your thoughts on how well this secondary goal is working for you the reader.

That being said, since I talked about Ruby’s Range this week, today’s Erlang function is lists:seq/2 and lists:seq/3.

If you remember from the sidebar of last weeks Erlang Thursday, the number at the end of the function name means the arity (number of arguments) of the function.

The function lists:seq/2 takes a beginning and an ending integer and produces a list of integers including both the beginning and ending value.

1
2
3
4
lists:seq(1, 10).    
% [1,2,3,4,5,6,7,8,9,10]
lists:seq(1, 1).
% [1]

The 3-arity version of lists:seq introduces the increment as the third argument:

1
2
lists:seq(1, 10, 3). 
% [1,4,7,10]

The increment value can be negative as well, allowing for counting down from one number to another.

1
2
3
4
lists:seq(20, 10, -1).
% [20,19,18,17,16,15,14,13,12,11,10]
lists:seq(20, 10, -5).
% [20,15,10]

The list:seq functions will throw an exception if given invalid starting and ending values, unlike the Ruby Range which returns an empty set.

1
2
3
4
5
6
7
8
9
10
11
lists:seq(10, 1).  
% ** exception error: no function clause matching lists:seq(10,1) (lists.erl, line 241)
lists:seq(1, 10, 0).
% ** exception error: no true branch found when evaluating an if expression
%      in function  lists:seq/3 (lists.erl, line 262)
lists:seq(1, 10, -2).
% ** exception error: no true branch found when evaluating an if expression
%      in function  lists:seq/3 (lists.erl, line 262)
lists:seq(10, 1, 2).
% ** exception error: no true branch found when evaluating an if expression
%      in function  lists:seq/3 (lists.erl, line 262)

–Proctor

Erlang Thursday – lists:member/2

To go with this weeks Ruby Tuesday post about Enumerable#include?, I decided I would highlight Erlang’s counterpart, lists:member/2.

Sidebar for those unfamiliar with Erlang: lists:member/2 is read as the function member with arity 2, which is found in the lists module. Arity being the number of arguments that the function takes. The module is important, because modules are the containers in which all functions must live — primarily because modules are the unit of code reloading in Erlang — but that way you know which specific member function is being referred to.

All that being said, the function member, in the lists module, takes two arguments: the item being looked for which is an Erlang term, and the list of Erlang terms to check; and returns true if the term is found in the list. An Erlang term is just a piece of data which can be of any of the Erlang data types.

For ability to try this out, the expression is normal, and the return value is the line that starts with the % symbol, which is the Erlang comment, to allow for copy and pasting into the Erlang shell erl.

It can be something as simple for checking if a number is in a list of numbers:

1
2
3
4
lists:member(4, [1, 2, 3, 5, 8, 13, 21]).
% false
lists:member(13, [1, 2, 3, 5, 8, 13, 21]).
% true

or if an atom is in a list of atoms:

1
2
3
4
lists:member(c, [a, b, c, d]).  
% true
lists:member(q, [a, b, c, d]).  
% false

or list of more complex terms such as a tuple, or tuples with lists inside them:

1
2
3
4
5
6
lists:member({d, 4}, [{a, 1}, {b, 2}, {c, 3}, {d, 4}]).
% true
lists:member({'Foo', [bar, baz]}, [a, 1, {'Foo', [bar, baz]}]).
% true
lists:member({fu, [bar, baz]}, [a, 1, {'Foo', [bar, baz]}]).   
% false

or even an integer, or “character”, in a string:

1
2
3
4
5
6
lists:member($a, "banana").
% true
lists:member(97, "banana").
% true
lists:member($A, "banana").
% false

Which if you look carefully enough, you might be able to get the hint that a string in Erlang is really just a list of integers.

Hope this is an interesting comparison between Ruby and Erlang, and my give you some insight into Erlang if you are unfamiliar with the language.

–Proctor