ESP32 Arduino: Getting started with the cpplinq library

In this tutorial we will check how to use the cpplinq library on the ESP32, which is a library of higher-order functions for range manipulation inspired by LINQ for C#. The tests shown on this tutorial were performed using an ESP32 board from DFRobot.

Introduction

In this tutorial we will check how to use the cpplinq library on the ESP32, which is a
library of higher-order functions for range manipulation inspired by LINQ for C#.

LINQ is a library used to execute queries in C# syntax against many different types of data [1]. Although it has many uses, one common use case corresponds to extract and process data from arrays or lists.

The cpplinq library offers similar functionality but in the C++ language, which means we can use it on the ESP32. You can check the GitHub page of the library here.

In this tutorial we are going to write a very simple use case where we are going to obtain the first even value of an array of integers.

For this tutorial we will be using the Arduino core. The tests shown here were performed using an ESP32 board from DFRobot.

Installing the library

Installing cpplinq as an Arduino library is really simple, as it is available as a single file. So, we need to go to the library page and click the big “download archive” button on the top right corner, as highlighted in figure 1.

Downloading the cpplinq library archive
Figure 1 – Downloading the library archive

You should get a .zip file. Extract it to a directory of your choice, on your computer. You should get a list of folders like the ones shown in figure 2. You should enter on the sourceCode folder.

Decompressing the .zip file of cpplinq
Figure 2 – Decompressing the cpplinq .zip file.

Inside the sourceCode folder, you should find a single folder called cpplinq. Inside, you should get some more folders, like shown in figure 3.

Getting inside the cpplinq library source code folder.
Figure 3 – cpplinq library source code folder.

From the folders shown in figure 3, copy the one named CppLinq. Then, locate your Arduino libraries folder and place there the folder you have just copied. After this, the cpplinq library should be available for importing in your Arduino environment.

The code

For this tutorial we will write a very simple example where we will select the first even element of an array of integers.

We will start our code by importing the cpplinq library we have just installed.

#include "cpplinq.hpp"

To make it easier to use the functions of the library, we will declare the use of the cpplinq namespace.

using namespace cpplinq;

Then, we will move on to the Arduino setup function, where we will write the rest of our code. The first thing we will do is opening a serial connection, so we can output the results of our program.

Serial.begin(115200);

Then, we will declare an array of integers, with some even and odd numbers. Note that, on the array declared below, the first even number is 4.

int ints[] = {5,7,4,7,8,15,9};

Then, we will start writing our cpplinq expression. In this case, it will be really simple since our aim is just to extract an even number from an array.

The first thing we need to do is creating a range from our array of integers. A range is an object on which the cpplinq query operators can be applied [2].

To construct a range from an array, we simply need to call the from_array function, passing as input our array of integers.

Then, to apply the query operator over our range, we need to use the “>>” operator, followed by the query operator we want to apply. Note that in C# linq we use the “.” operator instead.

In our case, followed by the “>>” operator, we are going to use the first query operator. This operator allows us to obtain the first element of a range that satisfies a defined condition (in our case, being an even integer).

Note that if no element is found, then an exception is thrown. If you don’t want to get an exception if no element is found, then you should use the first_or_default operator instead. This will return a default value if no element that fulfills our criteria is found.

Our condition is specified as a function that we will pass as input of the first operator. This function follows a pre-defined signature and it will be applied to all elements of our array, one by one, until it returns a Boolean value true for one of the elements.

So, as we already mentioned, the function will receive as input each element of the array and needs to return a Boolean, which means its signature should be something like:

bool isEven(int i){
  // code to evaluate if parameter is even
}

However, for more complex expression trees where we chain multiple operators, having named functions would make our code much more complex than it needs to be. Alternatively, we can pass as input of the cpplinq operators a C++ lambda function.

A lambda function is an anonymous function that we will be able to declare inline, as input of the first operator. So, the signature of our function in lambda syntax would be something like:

[](int i) {/* Code to evaluate if parameter is even*/ }

To check if a number is even, we simply need confirm it is divisible by 2. So, the body of our lambda function will be really compact:

[](int i) {return i%2 ==0;}

Putting our whole expression tree together, we obtain the following code to get the first even element of the array:

int result = from_array (ints)
             >> first([](int i) {return i%2 == 0;});       

To finalize, we are going to print the result to the serial port to confirm we obtain the value 4, as expected.

Serial.println(result); 

The final source code can be seen below.

#include "cpplinq.hpp"

using namespace cpplinq;

void setup() {
  Serial.begin(115200);
  
  int ints[] = {5,7,4,7,8,15,9};
  
  int result = from_array (ints)
               >> first([](int i) {return i%2 == 0;});
               
  Serial.println(result);  

}

void loop() {}

Testing the code

To test the code, simply compile it and upload it to your device using the Arduino core. Once the procedure finishes, open the Arduino IDE serial monitor. You should get an output similar to figure 4, which shows the first even number of our array getting printed.

Testing the cpplinq first operator on the ESP32.
Figure 4 – Output of the program.

As can be seen, the code for such operation is very compact. Taking in consideration that we can chain operations together, we tend to be able to do more complex processing of arrays / lists with fewer code than we would have if we looped over the content.

However, if you are not used to these kind of concepts (functional programming, high order functions, lambda syntax), this might seem very complex. Nonetheless, if you get used to it, it tends to produce much more compact, elegant and easier to read code.

One good exercise is to compare the amount of code we need to write using this approach versus using loops.

References

[1] https://www.codingame.com/playgrounds/213/using-c-linq—a-practical-overview/introduction

[2] https://mariusbancila.ro/blog/2012/10/28/cpplinq-range-generators-and-conversion-operators/

[3] http://www.drdobbs.com/cpp/linq-like-list-manipulation-in-c/240166882?pgno=1

Leave a Reply