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

,

Leave a Comment

Ruby Tuesday – Array#-

Today’s Ruby Tuesday is on Array#-.

Array#-, also called Array Difference, operates against an array, takes another array as its argument, and returns the items in the source array that are not in the second array.

[1, 2, 3, 4, 5] - [1, 2, 3, 5, 8]
# => [4]
[1, 2, 3, 4, 5] - [1, 2, 3, 6, 7, 8]
# => [4, 5]
[1, 2, 3, 6, 7, 8] - [1, 2, 3, 4, 5]
# => [6, 7, 8]
["a", "b", "c", "d"] - ["a", "s", "d", "f"]
# => ["b", "c"]
["a", "b", "c", "d"] - []
# => ["a", "b", "c", "d"]
[] - ["a", "s", "d", "f"]
# => []

As it is doing a difference between the two arrays, let’s add in some duplicate items and see what happens.

[1, 1, 2, 3, 5] - [2, 4, 6, 8]
# => [1, 1, 3, 5]
[1, 2, 2, 3,] - [2, 4, 6, 8]
# => [1, 3]

Based on the results we see that if there was a duplicate item in the source list that wasn’t in the second array, then we leave all those items in the source list.

If we have an item that is duplicated in the first list, and has an entry in the second list as well, then all occurences of that item get removed.

If we wanted more of a set difference behavior, we would have to either call uniq on at least the first array, if not both, or call uniq on the result of the difference.

[1, 1, 2, 3, 5].uniq - [2, 4, 6, 8].uniq
# => [1, 3, 5]
(main)> ([1, 1, 2, 3, 5] - [2, 4, 6, 8]).uniq
# => [1, 3, 5]

–Proctor

,

Leave a Comment

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},{1,[a,b]}}
queue:out_r(queue:new()).
% {empty,{[],[]}}

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

–Proctor

,

Leave a Comment

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

, , , , ,

Leave a Comment

Ruby Tuesday – Array#&

Today’s Ruby Tuesday continues on with the Array class and takes a look at Array#*.

Array#* does a set intersection between two arrays1, and an empty array is treated as an empty set.

[1, 2, 3, 4, 5] & []
# => []
[1, 2, 3, 4, 5] & [1, 3, 5]
# => [1, 3, 5]
[1, 2, 3, 4, 5] & [1, 3, 5, 7, 9]
# => [1, 3, 5]
[:a, :b, :c, :d] & [:a, 2, :foo]
# => [:a]
[:d] & [:a, :b, :c, :d]
# => [:d]

The Ruby documentation pages mentions that it uses the eql? and hash methods to determine if two elements are equal, so the elements only have to have the same value and not be the same reference.

[[1, 2], [3, 4], ["a", "b"]] & [[3, 4]]
# => [[3, 4]]
[3, 4].equal? [3, 4]
# => false
[3, 4].eql? [3, 4]
# => true

Array#& also keeps the order of the items as found in the original list for the items in the return value.

["a", "b", "c", "d", "e"] & ["c", "a", "t"]
# => ["a", "c"]

And as mentioned above, it is a set intersection, so no matter how many times an item appears in either array, it is only returned once.

[1, 2, 1, 3] & [1, 2]
# => [1, 2]
[1, 2, 1, 3] & [1, 1, 2]
# => [1, 2]
[1, 2, 1, 3] & [1, 1]
# => [1]

And by turning a String into an Array of characters, we can find all characters that are common between two strings.

"Supercalifragilisticexpialidocious".chars & "Me Ol' Bamboo".chars
# => ["e", "a", "l", "o"]

–Proctor


1. For those who are unfamiliar with what a set intersection is, it is finds all unique elements that are common between the two arrays.

,

Leave a Comment

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],1}}
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

,

Leave a Comment

Ruby Tuesday – Array#*

Today’s Ruby Tuesday cover’s Array#*.

Array#* either takes a integer, N, as its argument, in which case it concatenates N copies of the array together and uses the result as it return value.

[1, 2, 3, 4, 5] * 3
% => [1, 2, 3, 4, 5, 1, 2, 3, 4, 5, 1, 2, 3, 4, 5]
["a", "b", "c"] * 4
% => ["a", "b", "c", "a", "b", "c", "a", "b", "c", "a", "b", "c"]
[1, [:a, [:b, [:c]]]] * 2
% => [1, [:a, [:b, [:c]]], 1, [:a, [:b, [:c]]]]

Or it can take a string as its argument, in which case, it returns a flattened join of the items in the array with the string argument as the separator.

["a", "b", "c"] * ","
% => "a,b,c"
["a", "b", "c"] * "at"
% => "aatbatc"
[1, 2, 3, 4, 5] * ''
% => "12345"
[:x, :y, :z] * ';'
% => "x;y;z"
[[:a, 1], [:b, 2], [:c, 3]] * ';'
% => "a;1;b;2;c;3"
[1, [:a, [:b, [:c]]]] * ';'
% => "1;a;b;c"

Notice how multiplying by a string returns a flattened array joined together, instead of just the top level elements of an array with to_s called on them joined together.

–Proctor

,

Leave a Comment

Erlang Thursday – queue:peek/1

For today’s Erlang Thursday we continue looking at the queue module and look at queue:peek/1 from the Extended API.

queue:peek/1 takes a queue as it’s argument and returns either the atom empty if the queue is empty, or {value, Item} where Item is the item at the head of the queue.

QueueOne = queue:from_list([1, 2, 3, 4, 5]).
% {[5,4],[1,2,3]}
queue:peek(QueueOne).
% {value,1}
QueueOne.
% {[5,4],[1,2,3]}
EmptyQueue = queue:new().
% {[],[]}
queue:peek(EmptyQueue).
% empty

queue:peek/1 does not modify the existing queue at all either, so we can call it once as seen above, or multiple times as below, and the queue we peeked at doesn’t change.

QueueTwo = queue:from_list([a, b, c, d, e, f]).
% {[f,e],[a,b,c,d]}
queue:peek(QueueTwo).
% {value,a}
queue:peek(QueueTwo).
% {value,a}
queue:peek(QueueTwo).
% {value,a}
QueueTwo.
% {[f,e],[a,b,c,d]}

And unlike we saw in the previous Erlang Thursday on queue:head/1, we can safely peek at an empty queue instead of getting an exception.

queue:head(EmptyQueue).
% ** exception error: empty
%      in function  queue:head/1
%         called as queue:head({[],[]})
queue:peek(EmptyQueue).
% empty

Erlang’s queue module also contains queue:peek_r/1 which will peek at the element at the rear of the queue.

queue:peek_r(EmptyQueue).
% empty
queue:peek_r(QueueOne).
% {value,5}
queue:peek_r(QueueOne).
% {value,5}
queue:peek_r(QueueOne).
% {value,5}
queue:peek_r(QueueTwo).
% {value,f}
QueueTwo.
% {[f,e],[a,b,c,d]}
QueueOne.
% {[5,4],[1,2,3]}
EmptyQueue.
% {[],[]}

–Proctor

,

Leave a Comment

Ruby Tuesday – Array#first

As we continue looking to see how Ruby’s Array class can be seen as a queue, we take a look at Array#first.

Array#first returns the first element of an Array, or nil if the array is empty.

[1, 2 ,3, 4, 5].first
# => 1
[].first
# => nil
[{:a => 1}, :b, [1, 2, 3]].first
# => {:a=>1}

While this in and of itself is nothing spectacular, what it gets us is a way of having Command/Query Separation1, or CQS for short.

Why care about Command/Query Separation?

First, by using it we can start to take a more functional approach to our design. We can “peek” at the first element of an array, and keep peeking to our hearts content and never worry about modifying the state of the queue.

Second, when it is time to “pop” the next element off the queue, we can have the result of the “pop” command be to return a new queue object that is the result of dropping the first item from the array.

This allows us to empty a queue without modifying the original queue.

my_queue = [1, 2, 3, 4, 5]
# => [1, 2, 3, 4, 5]
my_queue.first #peek
# => 1
my_queue.first #peek again
# => 1
after_pop = my_queue.drop(1)
# => [2, 3, 4, 5]
after_pop
# => [2, 3, 4, 5]
my_queue
# => [1, 2, 3, 4, 5]

–Proctor


1. Command/Query Separation states that a method should either return a value, or modify state, but never do both.

,

Leave a Comment

Erlang Thursday – queue:tail/1

In today’s Erlang Thursday we continue with the queue module’s Okasaki API, and look at queue:tail/1.

queue:tail/1 takes a non-empty queue as its argument, and returns a new queue with the first element removed.

Queue = queue:from_list([1, 2, 3, 4, 5]).
% {[5,4],[1,2,3]}
Tail = queue:tail(Queue).
% {[5,4],[2,3]}
Queue.
% {[5,4],[1,2,3]}
queue:head(Tail).
% 2
queue:to_list(Tail).
% [2,3,4,5]

We can see above that calling queue:tail/1 is not a destructive operation as might happen in other languages, and does indeed leave the original queue intact.

As part of the Okasaki API, which treats a queue as a double ended, queue:tail/1 has a counterpart function queue:liat/1 which will return a new queue with last item removed. queue:liat/1 also has an alias in the Okasaki API of queue:init/1.

queue:liat(Queue).
% {[4],[1,2,3]}
queue:init(Queue).
% {[4],[1,2,3]}
Queue.
% {[5,4],[1,2,3]}

Note that the Erlang documentation also shows that there is an alias queue:lait/1 which it points out should not be used because it is a misspelling.

And because we want to try to break things and see what we can learn, let’s try to call the different tail functions we have covered so far with an empty queue to see what happens.

EmptyQueue = queue:new().
% {[],[]}
queue:tail(EmptyQueue).
% ** exception error: empty
%      in function  queue:drop/1
%         called as queue:drop({[],[]})
queue:liat(EmptyQueue).
% ** exception error: empty
%      in function  queue:drop_r/1
%         called as queue:drop_r({[],[]})
queue:init(EmptyQueue).
% ** exception error: empty
%      in function  queue:drop_r/1
%         called as queue:drop_r({[],[]})

Looks like we get exception errors in queue:drop/1 and queue:drop_r/1 when we call queue:tail/1 and queue:liat/1 respectively.

And when we look at the behavior of queue:drop/1 and queue:drop_r/1 with a queue with items in it, it looks like queue:tail/1 is just an alias for queue:drop/1, and queue:liat/1 and queue:init/1 are just aliases for queue:drop_r/1.

queue:drop(Queue).
% {[5,4],[2,3]}
queue:drop_r(Queue).
{[4],[1,2,3]}

–Proctor

,

Leave a Comment