Tag Archives: Erlang

Erlang Thursday – c:xm/1

Today’s Erlang Thursday takes a turn down a slightly different route and takes a look in the c module at c:xm/1.

c:xm/1 takes either a atom, representing the name of a module, or a string, representing a filename, and inspects that module for unused and undefined functions, as well as calls to deprecated functions.

First let’s take a look at the erlang module, and see if there is anything in there that is deprecated.

c:xm(erlang).
% [{deprecated,[]},{undefined,[]},{unused,[]}]

Looks like there are no calls to deprecated functions, no calls to undefined functions, and no unused functions floating around in the erlang module. Note: This is running under Erlang 17.3.4, and you may get a different result depending on the version of Erlang you are running, because erlang:now/0 has been deprecated as of v18.0.

Trying to come up with an example of an existing module that might have some of these criteria, I took a look at the README for Erlang 17.0, and did a search for deprecated. Doing that there was a note:

The module pg has been deprecated and will be removed in Erlang/OTP 18.

So let’s pass that module to c:xm/1 and see what we get.

c:xm(pg).
% [{deprecated,[{{pg,create,1},{pg,master,1}},
%               {{pg,create,2},{pg,master,1}}]},
%  {undefined,[]},
%  {unused,[]}]

And we can see that we do get information back about deprecated functions in the pg module.

While the odds are low that you will need to use this function in your normal day to day work, as the tooling around Erlang generally seems to take care of this for you, this was intriguing enough that it seemed worthy of calling it out, especially if for those time when the compilation of Erlang code is done from inside the Erlang shell.

–Proctor

Guest on Three Devs and a Maybe

I was recently asked to be on the podcast Three Devs and a Maybe, and am happy to announce that episode is now live.

I talked about my background of getting into computers, my route into functional programming, Clojure, Erlang, and a little bit off background on how I decided to start Functional Geekery.

Make sure to take a listen to Episode 71 – Erlang and Clojure with Steven Proctor and let me know what you think.

Thanks to Edd Mann and Michael Budd for the invite, and a great conversation.

–Proctor

Erlang Thursday – ordsets:is_subset/2

Today’s Erlang Thursday covers ordsets:is_subset/2.

ordsets:is_subset/2 takes two Ordered Sets, and checks if the ordered set passed in as the first argument is a subset of ordered set passed in as the argument. For a given set, Set A, to be a subset of another set, Set B, every item in Set A must also be a member of Set B.

SetA = ordsets:from_list(lists:seq(1, 10)).
% [1,2,3,4,5,6,7,8,9,10]
SetB = ordsets:from_list(lists:seq(2, 10, 2)).
% [2,4,6,8,10]
SetC = ordsets:from_list(lists:seq(1, 15, 3)).
% [1,4,7,10,13]
EmptySet = ordsets:new().
% []
ordsets:is_subset(SetB, SetA).
% true
ordsets:is_subset(SetA, SetB).
% false
ordsets:is_subset(SetC, SetA).
% false

And for those who aren’t as familiar with set theory, a few quick facts about sets. First, the empty set is a subset of all sets; second, a set is considered a sub-set of itself; and lastly, a given Set B is a superset of Set A, if Set A is subset of Set B.

ordsets:is_subset(EmptySet, SetA).
% true
ordsets:is_subset(EmptySet, SetB).
% true
ordsets:is_subset(EmptySet, SetC).
% true
ordsets:is_subset(EmptySet, EmptySet).
% true
ordsets:is_subset(SetA, SetA).
% true

–Proctor

Erlang Thursday – ordsets:subtract/2

Today’s Erlang Thursday is on ordsets:subtract/2.

ordsets:subtract/2 takes two ordered sets as its arguments, and returns a ordered set containing the items of the first ordered set that are not in the second ordered set.

OrderedSetA = ordsets:from_list([5, 4, 3, 2, 1]).
# [1,2,3,4,5]
OrderedSetB = ordsets:from_list([1, 1, 2, 3, 5, 8, 13]).
# [1,2,3,5,8,13]
OrderedSetC = ordsets:from_list([2, -2, 4, -4, 16, -16]).
# [-16,-4,-2,2,4,16]
EmptySet = ordsets:new().
# []
ordsets:subtract(OrderedSetA, OrderedSetB).
# [4]
ordsets:subtract(OrderedSetA, EmptySet).
# [1,2,3,4,5]
ordsets:subtract(OrderedSetB, EmptySet).
# [1,2,3,5,8,13]
ordsets:subtract(EmptySet, OrderedSetA).
# []
ordsets:subtract(OrderedSetB, OrderedSetC).
# [1,3,5,8,13]

And note that ordsets:subtract/2 is not commutative, unlike ordsets:union/2 or ordsets:intersection/2.

ordsets:subtract(OrderedSetA, OrderedSetC).
# [1,3,5]
ordsets:subtract(OrderedSetC, OrderedSetA).
# [-16,-4,-2,16]

And again, your friendly reminder if you haven’t been following along, just because Ordered Sets in Erlang are represented as a List, doesn’t mean that Lists are Ordered Sets.

–Proctor

Erlang Thursday Bonus! Performace of erlang:length/1 on a list

A bonus Erlang Thursday for everyone.

Giving the Dallas/Fort Worth Erlang User group presentation last week, we had a couple of people new to Erlang make it to our meeting, and the question was raised:

Do lists have any smarts around knowing their length, or does it have to run through all the items to calculate the length?

I was 99% sure that Erlang has to run through the list every time, since it uses linked lists style data structures for it’s list, but wasn’t sure if there might be something smart in the implementation that I wasn’t aware of to speed up that functionality.

In putting together the regularly scheduled Erlang Thursday post for today, I realized I should have busted out timer:tc to demonstrate the behavior of erlang:length/1 by showing how long it takes to get the length of different lists.

So in honor of that question, and as a reminder to review it at the next user group meeting, I am documenting the behavior here. And remember, that the first item in the result tuple is the time in microseconds the operation took.

timer:tc(erlang, length, [lists:seq(1, 10)]).
{2,10}
timer:tc(erlang, length, [lists:seq(1, 1000)]).
{5,1000}
timer:tc(erlang, length, [lists:seq(1, 10000)]).
{41,10000}
timer:tc(erlang, length, [lists:seq(1, 100000)]).
{134,100000}
timer:tc(erlang, length, [lists:seq(1, 1000000)]).
{1918,1000000}
timer:tc(erlang, length, [lists:seq(1, 10000000)]).
{25139,10000000}
timer:tc(erlang, length, [lists:seq(1, 100000000)]).
{1368691,100000000}

After about 1000 items in a linked list, we start growing lineraly in the time it takes to count the items, so if it is not doing an actual traversal of all the items, it has the same scale of doing so as far as the order of operations (Big-O) goes.

–Proctor

Erlang Thursday – ordsets:intersection/2

Today’s Erlang Thursday looks some more at that ordsets module and covers ordsets:intersection/2.

ordsets:intersection/2 takes two ordered sets and returns a new ordered set that is the intersection of the two ordered sets provided. For those who don’t have a background wth set theory, all a set intersection is is the set of items that all the sets we are intersecting have in common.

OrderedSet1 = ordsets:from_list([1, 2, 1, 3, 2, 4, 4, 9]).
[1,2,3,4,9]
OrderedSet2 = ordsets:from_list([1, 3, 5, 7, 9]).
[1,3,5,7,9]
ordsets:intersection(OrderedSet1, OrderedSet2).
[1,3,9]
ordsets:intersection(OrderedSet2, OrderedSet1).
[1,3,9]

Because ordsets:intersection/2 looks for the common elements in the ordered sets, it is commutative, and as we see above, we get the same result regardless of which order we pass in the two ordered sets as arguments.

If there are no items in common, the returned result is an empty ordered set (really an empty list, but see last week’s post on ordsets:union/2 on the dangers of just using a list as a ordered set).

Evens = ordsets:from_list(lists:seq(2, 20, 2)).
[2,4,6,8,10,12,14,16,18,20]
Odds = ordsets:from_list(lists:seq(1, 20, 2)).
[1,3,5,7,9,11,13,15,17,19]
ordsets:intersection(OrderedSet2, ordsets:new()).
[]
ordsets:intersection(Evens, Odds).
[]

Erlang also provides ordsets:intersection/1, that takes a list of ordered sets as its argument, and returns the intersection of all the ordered sets in that list.

OrderedSet3 = ordsets:from_list([1, 1, 2, 3, 5, 8]).
[1,2,3,5,8]
ordsets:intersection([Evens, Odds, OrderedSet1]).
[]
ordsets:intersection([Odds, OrderedSet2, OrderedSet1]).
[1,3,9]
ordsets:intersection([Evens, OrderedSet1, OrderedSet3]).
[2]
ordsets:intersection([Odds, OrderedSet1, OrderedSet3]).
[1,3]

–Proctor

Erlang Thursday – ordsets:union/2

Today’s Erlang Thursday is on ordsets:union/2.

ordsets:union/2 takes two ordered sets and returns an merged ordered set of the arguments.

SetA = ordsets:from_list([1, 1, 2, 3, 5]).
% [1,2,3,5]
SetB = ordsets:new().
% []
SetC = ordsets:from_list([3, 1, 4, 1, 5, 9]).
% [1,3,4,5,9]
SetD = ordsets:from_list([a, b, c, d, e]).
% [a,b,c,d,e]
UnionAB = ordsets:union(SetA, SetB).
% [1,2,3,5]
UnionAC = ordsets:union(SetA, SetC).
% [1,2,3,4,5,9]

And because a string in Erlang is just a list of characters, we can also create ordered sets from strings, and then get a union of the unique characters that are in two strings.

ordsets:from_list("Kermit").
% "Keimrt"
ordsets:from_list([75, 101, 114, 109, 105, 116]).
% "Keimrt"
ordsets:from_list("Mississippi").
% "Mips"
ordsets:union(ordsets:from_list("Kermit"), ordsets:from_list("Mississippi")).
% "KMeimprst"

The ordsets modules also contains ordsets:union/1, which takes a list of ordered sets and returns the union of all the ordered sets in the list.

UnionAC = ordsets:union([SetA, SetC]).
% [1,2,3,4,5,9]
UnionABC = ordsets:union([SetB, SetC, SetA]).
% [1,2,3,4,5,9]
UnionABCD = ordsets:union([SetB, SetC, SetA, SetD]).
% [1,2,3,4,5,9,a,b,c,d,e]
UnionCD = ordsets:union([SetC, SetD]).
% [1,3,4,5,9,a,b,c,d,e]

WARNING: While the representation for an ordered set is just a list, if you pass a list to ordsets:union/2 you will not get what you expect, as it expects the items in each “ordered set” to actually be ordered and a set.

ordsets:union([1, 2, 3], [a, b, c]).
% [1,2,3,a,b,c]
ordsets:union([1, 1, 2, 3, 1, 2], [a, b, c]).
% [1,1,2,3,1,2,a,b,c]
ordsets:union([1, 1, 2, 3, 1, 2], [1, a, b, c]).
% [1,1,2,3,1,2,a,b,c]
ordsets:union([1, 1, 2, 3, 1, 2], [1, a, b, c, 1]).
% [1,1,2,3,1,2,a,b,c,1]

–Proctor

Erlang Thrusday – queue:out/1

Today’s Erlang Thursday covers queue:out/1 from the queue module’s Original API.

queue:out/1 is one of my all time Queue fuctions, or methods, that I have seen, and that is across all the languages and libraries that I have encountered.

“What makes it so great?”, I can hear you asking.

That would be it’s combination of tuples, tagged tuples, immutability, forgivingness, and the fact that after seeing the result, it makes me wish more Queue implementations had an API like this.

First there have been many times in my past where either myself, or someone else, has forgotten to do a check to see if a queue is empty before trying to pop the first item from it, and that mistake has resulted in a not-so-nice runtime error.

queue:out/1 on the other hand, doesn’t trigger an error when you try to call it on an empty queue. Rather it returns a tagged tuple telling you that the queue you tried to call out on was empty, and the empty queue.

queue:out(queue:new()).
% {empty,{[],[]}} 

If we do pass in a non-empty queue, queue:out/1 returns a two tuple, with the first element being a tagged tuple that tells us we got a value out and the HEAD of the original queue, and for the second element, we get a new queue with the result of removing the first item.

Queue = queue:from_list([a, b, c, d]).
% {[d],[a,b,c]}
queue:out(Queue).
% {{value,a},{[d],[b,c]}}
Queue.
% {[d],[a,b,c]}
{{value, Head}, NewQueue} = queue:out(Queue).
% {{value,a},{[d],[b,c]}}
Queue.
% {[d],[a,b,c]}
Head.
% a
NewQueue.
% {[d],[b,c]}
queue:head(NewQueue).
% b

When dealing with the abstract notion of a queue across any language, the concept of a “pop” does two things, returns the top item of the queue, and modifies the queue to have that item removed.

Since Erlang queues are immutable, after you think about it for a few minutes, it starts to make sense that queue:out/1 handles both those behaviors of “pop” by returning both the item removed from the queue, and the new state of the queue with that item removed.

Erlang’s queue module also provides a function queue:out_r/1 which behaves the same as queue:out/1 except it operates off the last item in the queue, instead of the first item.

queue:out_r(queue:from_list([a, b, c, d])).
% {{value,d},{,[a,b]}}
queue:out_r(queue:new()).
% {empty,{[],[]}}

I hope you found queue:out/1 as handy and as nice I have,

–Proctor

DFW Erlang – Erlang, Elixir, and LFE on a Raspberry Pi

For those of you who are, or will be, in the Dallas/Fort Worth area, this is your friendly reminder that next Wednesday, July 1st, will be our monthly DFW Erlang User Group meeting.

We have recently moved to be hosted by Improving Enterprises, and now meet on the first Wednesday of the month.

This upcoming meeting, I will be going over different Erlang VM languages running on a Raspberry Pi. We will show Erlang, Elixir, and LFE running and see how many processes we can manage to kick off on a Raspberry Pi with 435MB of memory.

To RSVP and join us you can find the meeting announcement on Meetup.com here.

If you can’t join us at this meeting, we would love to see you at a future meeting.

And lastly, I want to give a great big Thank You to Duncan McGreggor and Robert Virding for all of their help in getting LFE setup on a Raspberry Pi. And another Thank You to Duncan for coming up with a demo for LFE after asking him if he knew of any good LFE projects that show off a number of processes being spawned up and interacting to push the bounds of a Raspberry Pi. If you can’t make it to our user group, make sure to check out his project at https://github.com/oubiwann/laotzi-demo.

–Proctor

Erlang Thursday – queue:split/2

Today’s Erlang Thursday is on queue:split/2 from the queue modules Original API.

queue:split/2 takes two arguments. The first argument being a integer N from 0 to X, where X is number of items in the queue, and the second argument is the queue that we wish to split. The return value is a two-tuple with a the first item being a queue of the first N items, and the second item in the tuple is a queue of the rest of the items.

QueueOne = queue:from_list([a, 1, b, 2, c, 3, 4]).
% {[4,3,c],[a,1,b,2]}
queue:split(4, QueueOne).
% {{[2],[a,1,b]},{[4,3],}}
queue:split(0, QueueOne).
% {{[],[]},{[4,3,c],[a,1,b,2]}}
queue:split(1, QueueOne).
% {{[],[a]},{[4,3,c],[1,b,2]}}
queue:split(7, QueueOne).
% {{[4,3,c],[a,1,b,2]},{[],[]}}
queue:split(15, QueueOne).
% ** exception error: bad argument
%      in function  queue:split/2
%         called as queue:split(15,{[4,3,c],[a,1,b,2]})
{SplitFirst, SplitSecond} = queue:split(3, QueueOne).
% {{[b,1],[a]},{[4,3,c],[2]}}
SplitFirst.
% {[b,1],[a]}
SplitSecond.
% {[4,3,c],[2]}
queue:peek(SplitFirst).
% {value,a}
queue:peek(SplitSecond).
% {value,2}

Erlang also provides a queue:join/2 function that takes two queues, and returns a new queue, with the queue that was passed as the second argument appended to the queue passed in as the first argument.

queue:join(SplitFirst, SplitSecond).
% {[4,3,c],[a,1,b,2]}
queue:join(SplitSecond, SplitFirst).
% {[b,1],[2,c,3,4,a]}
queue:join(queue:new(), SplitFirst).
% {[b,1],[a]}
queue:join(queue:new(), queue:new()).
% {[],[]}

–Proctor