ESP8266 Arduino: Testing the cpplinq library

In this tutorial we will check how to use the cpplinq library on the ESP8266. The tests shown on this tutorial were performed on a DFRobot’s ESP8266 FireBeetle board.

Introduction

In this tutorial we will check how to use the cpplinq library on the ESP8266.

Cpplinq is a library of high order functions for range manipulation inspired in C# LINQ [1].

Note that we have already covered the use of a lot of cpplinq operators on the ESP32, in previous tutorials. Nonetheless, since cpplinq is a generic C++ library, those tutorials should also work on the ESP8266. You can check the list of tutorials on the “Related Posts” section.

So, in this getting started tutorial we will check how to use some of the basic operators of cpplinq.

For the installation instructions, please check the “Installing the library” section of this post. The procedure shown there is the same for the ESP8266.

Note that we are covering very simple use cases of applying the cpplinq operators over an array of integers, for demonstration purposes. Nonetheless, these operators can also be applied over arrays of objects, for example, which is a use case where the library is really useful for real application scenarios.

The tests shown on this tutorial were performed on a DFRobot’s ESP8266 FireBeetle board.

The code

The first thing we will do is importing the cpplinq library.

#include "cpplinq.hpp"

Then we will declare the use of the cpplinq namespace.

using namespace cpplinq;

After this we will move on to the Arduino setup, where we will write the rest of the code. We will start by opening a serial connection, to output the results of our program.

Serial.begin(115200);

Then we will define an array of integers, which will be the base of our operations. Since the cpplinq operators don’t mutate our array but rather produce new sequences, we can use this same array for multiple tests.

int ints[] = {107, 1, 80, 3, 8, 20, 30, 5, 77, 102};

Note however that, before we are able to apply the cpplinq operators, we need to convert our array to a range object. This is done with a call to the from_array function.

So, the first thing we will do is obtaining the element of the array with the maximum value. For that we can simply use the max operator, which receives no parameters.

The full expression tree is shown below. As mentioned, we first need to convert the array to a range and then apply the desired operator. Note that these calls are chained by using the >> operator.

int maxVal = from_array(ints)
             >> max();

After obtaining the value, we will print it to the serial port.

Serial.print("Max element of the array: ");
Serial.println(maxVal);

We will now do a similar procedure, but to obtain the minimum element of the array. For this we use the min operator, as shown below.

int minVal = from_array(ints)
             >> min();

We will also print the result obtained.

Serial.print("Min element of the array: ");
Serial.println(minVal);

Other useful operation is reversing our array. To do that, we simply need to use the reverse operator, which also takes no arguments.

This operator returns a range with the reversed elements, which we need to convert to a data type that we can iterate, in order to be able to print and confirm the results. For that we will use the to_vector operator, which will return a C++ vector.

auto reversed = from_array(ints)
               >> reverse()
               >> to_vector();

Then, to print the values of the result, we simply need to iterate the vector.

for(int i=0; i<reversed.size(); ++i){
    Serial.print(reversed[i]);
    Serial.print("|");
}

To finalize, we will illustrate a slightly more complex use case where we will filter the array to return only the numbers that are greater than 10, and then order the result.

As before, we first need to convert the array to a range object.

from_array(ints)

The filtering part is done with the where operator. This operator receives as input a function that will be applied to each individual element of the range.

This function should return the Boolean value true if the element being evaluated fills our criteria (it is greater than 10), and return false otherwise.

For a more compact code, we will declare this function using the C++ lambda syntax.

where([](int i) {return i > 10;})

After the filtering, we just need to apply the orderby_ascending operator to do the ordering. This operator also receives as input a function, which is applied over each element of the array.

For each element, this function should specify what value should be used in the ordering. This is useful for when we are ordering an array of objects, where each object has multiple fields. Thus, we can specify which field should be used as ordering criteria.

In our case, since we are iterating over an array of integers, we should just return the current element.

orderby_ascending([](int i) {return i;})

After ordering, we need to convert the range to a vector, like we did before, to be able to print its elements.

to_vector();

The full expression tree plus the printing of the elements of the vector is shown below.

auto filtered = from_array(ints)
               >> where([](int i) {return i > 10;})
               >> orderby_ascending([](int i) {return i;})
               >> to_vector();

Serial.print("\nFiltered Array: ");

for(int i=0; i<filtered.size(); ++i){
    Serial.print(filtered[i]);
    Serial.print("|");
}

The full source code can be seen below.

#include "cpplinq.hpp"
 
using namespace cpplinq;
 
void setup() {
  Serial.begin(115200);
  Serial.println("\n\n");
   
  int ints[] = {107, 1, 80, 3, 8, 20, 30, 5, 77, 102};

  int maxVal = from_array(ints)
               >> max();

  Serial.print("Max element of the array: ");
  Serial.println(maxVal);
 
  int minVal = from_array(ints)
               >> min();

  Serial.print("Min element of the array: ");
  Serial.println(minVal);

  auto reversed = from_array(ints)
               >> reverse()
               >> to_vector();

  Serial.print("Reversed Array: ");

  for(int i=0; i<reversed.size(); ++i){
    Serial.print(reversed[i]);
    Serial.print("|");
  }
 
  auto filtered = from_array(ints)
               >> where([](int i) {return i > 10;})
               >> orderby_ascending([](int i) {return i;})
               >> to_vector();

  Serial.print("\nFiltered Array: ");

  for(int i=0; i<filtered.size(); ++i){
    Serial.print(filtered[i]);
    Serial.print("|");
  }
}
 
void loop() {}

Testing the code

To test the code, simply compile it and upload it to your device, using the Arduino IDE. After this procedure finishes, open the serial monitor. You should get an output similar to figure 1.

As can be seen, we have obtained the minimum and maximum elements of the array, by applying the min and max operators, respectively. We have also obtained the reversed array and then, in the last operation, we obtain the array with elements greater than 10, sorted by ascending order.

Output of the program, on the Arduino IDE serial monitor, showing the result of applying different cpplinq operators to the array of integers.
Figure 1 – Output of the program.

Related Posts

References

[1] https://github.com/mrange/cpplinq

Leave a Reply