Set-Theoretic Operations

How can you combine collections together?

We explore the set-theoretic operations provided by Lasp. Each of these functions takes, as input, a two source collections and creates a single output collection. The output will be maintained as the input is modified, and these operators can be chained arbitrarily.

Product Operation

Let's start by creating two input collections and an output collection.

1> {ok, {LeftId, _, _, _}} = lasp:declare({<<"left">>, state_orset}, state_orset).              
{ok,{{<<"left">>,state_orset},
     state_orset,
     [{clock,[{<<170,227,142,126,63,64,19,227,195,66,39,125,58,
                 195,75,134,148,109,168,...>>,
               1}]}],
     {state_orset,[]}}}
2> {ok, {RightId, _, _, _}} = lasp:declare({<<"right">>, state_orset}, state_orset).
{ok,{{<<"right">>,state_orset},
     state_orset,
     [{clock,[{<<170,227,142,126,63,64,19,227,195,66,39,125,58,
                 195,75,134,148,109,168,...>>,
               1}]}],
     {state_orset,[]}}}
3> {ok, {ProductId, _, _, _}} = lasp:declare({<<"product">>, state_orset}, state_orset).
{ok,{{<<"product">>,state_orset},
     state_orset,
     [{clock,[{<<170,227,142,126,63,64,19,227,195,66,39,125,58,
                 195,75,134,148,109,168,...>>,
               1}]}],
     {state_orset,[]}}}

Now, let's instruct the system to compute the Cartesian product of these two collections, and place the output in it's own collection.

4> lasp:product(LeftId, RightId, ProductId).
ok

Now, let's insert some values into the collections.

5> lasp:update(LeftId, {add, 1}, self()).
{ok,{{<<"left">>,state_orset},
     state_orset,
     [{clock,[{<<170,227,142,126,63,64,19,227,195,66,39,125,58,
                 195,75,134,148,109,168,...>>,
               2}]}],
     {state_orset,[{1,
                    [{<<238,140,18,224,53,159,36,82,45,233,15,19,116,65,95,
                        234,...>>,
                      true}]}]}}}
6> lasp:update(RightId, {add, 1}, self()).
{ok,{{<<"right">>,state_orset},
     state_orset,
     [{clock,[{<<170,227,142,126,63,64,19,227,195,66,39,125,58,
                 195,75,134,148,109,168,...>>,
               2}]}],
     {state_orset,[{1,
                    [{<<255,58,60,173,193,138,15,227,94,88,201,220,12,106,56,
                        116,...>>,
                      true}]}]}}}

Let's verify we have the right result: in this case it will be a collection of pairs, represented as Erlang tuples.

7> {ok, ProductResult} = lasp:query(ProductId), sets:to_list(ProductResult).
[{1,1}]

Union

Now, we can also use these initial collections to perform a union.

Let's declare a place for the results.

8> {ok, {UnionId, _, _, _}} = lasp:declare({<<"union">>, state_orset}, state_orset).    
{ok,{{<<"union">>,state_orset},
     state_orset,
     [{clock,[{<<170,227,142,126,63,64,19,227,195,66,39,125,58,
                 195,75,134,148,109,168,...>>,
               1}]}],
     {state_orset,[]}}}

Let's perform the union.

9> lasp:union(LeftId, RightId, UnionId).
ok

Finally, let's look at the output.

10> {ok, UnionResult} = lasp:query(UnionId), sets:to_list(UnionResult).           
[1]

Intersection

Intersection operates in a similar way as well.

11> {ok, {IntersectionId, _, _, _}} = lasp:declare({<<"intersection">>, state_orset}, state_orset).
{ok,{{<<"intersection">>,state_orset},
     state_orset,
     [{clock,[{<<170,227,142,126,63,64,19,227,195,66,39,125,58,
                 195,75,134,148,109,168,...>>,
               1}]}],
     {state_orset,[]}}}
12> lasp:intersection(LeftId, RightId, IntersectionId).                
ok
13> {ok, IntersectionResult} = lasp:query(IntersectionId), sets:to_list(IntersectionResult).
[1]