Functional Operations

How you can transform, combine and operate with sets in a functional way.

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

Map Operation

First, declare a source set.

> {ok, {SourceId, _, _, _}} = lasp:declare({<<"source">>, state_orset}, state_orset).
{ok,{{<<"source">>,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,[]}}}

Then, declare a destination set.

> {ok, {DestinationId, _, _, _}} = lasp:declare({<<"destination">>, state_orset}, state_orset).
{ok,{{<<"destination">>,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 map the values from one set into the other, and double the elements.

> lasp:map(SourceId, fun(X) -> X * 2 end, DestinationId).
ok

Now, we can add an element to the first set and see the results of the transformation in the destination set!

> lasp:update(SourceId, {add, 1}, self()).               
{ok,{{<<"source">>,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,
                    [{<<124,101,224,70,103,26,222,240,141,97,96,128,120,143,
                        228,148,...>>,
                      true}]}]}}}
> lasp:query(DestinationId).
{ok,{set,1,16,16,8,80,48,
         {[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[]},
         {{[],[],[],[],[],[],[2],[],[],[],[],[],[],[],[],[]}}}}
> {ok, Result} = lasp:query(DestinationId), sets:to_list(Result).
[2]

Filter Operation

Now, assuming we still have the source set declared from the section above, we can apply a filter directly to it.

First, let's declare somewhere to store the results.

> {ok, {FilteredId, _, _, _}} = lasp:declare({<<"filtered">>, state_orset}, state_orset).      
{ok,{{<<"filtered">>,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 apply a filter that only allows even elements through.

> lasp:filter(SourceId, fun(X) -> X rem 2 == 0 end, FilteredId). 
ok

Since the source set only has 1 in it, the filtered set should be empty!

> {ok, Result1} = lasp:query(FilteredId), sets:to_list(Result1).
[]

But, if we add an element to the set that's even, we should see the output in the filtered set.

> lasp:update(SourceId, {add, 2}, self()).                                    {ok,{{<<"source">>,state_orset},
     state_orset,
     [{clock,[{<<170,227,142,126,63,64,19,227,195,66,39,125,58,
                 195,75,134,148,109,168,...>>,
               3}]}],
     {state_orset,[{1,
                    [{<<124,101,224,70,103,26,222,240,141,97,96,128,120,143,
                        228,148,...>>,
                      true}]},
                   {2,
                    [{<<82,188,56,236,83,244,32,79,114,44,4,33,148,226,184,...>>,
                      true}]}]}}}
                                                                                  
> {ok, Result2} = lasp:query(FilteredId), sets:to_list(Result2).
[2]

🚧

Fold Operation

We avoid discussion of the fold operation here, as it's currently being revised and the interface i the prototype is less than desirable at the current moment.