30 de julho de 2021

Do bit Ao Byte

Embarcados, Linux e programação

Funções lambda C++

funções lambda

No artigo anterior vimos a resposta do Desafio maker 03, utilizando uma função lambda. As funções lambda são úteis para chamadas inline principalmente em códigos que não haverá reutilização da função, economizando tempo de desenvolvimento em declarações de funções.

Seu formato:

[ cláusula de captura ] (parâmetros) -> tipo de retorno {definição de método}

O tipo de retorno para o sort do desafio não é necessário, portanto não foi utilizado, uma vez que o propósito era exclusivamente ordenar o array original.

Uma das funções lambda é o for_each:

for_each

Supondo a declaração da proposta do Desafio maker 03:

//DESAFIO MAKER 03: Ordenar um array
#include <bits/stdc++.h>

//se for fazer no PC/notebook, use assim:
using namespace std;

...

//se for fazer no Arduino/ESP, faça no setup
int main(){
    vector <int> v {4,1,4,3,4,1,5,7};
    //resto do código...
}

Poderíamos exibir os valores assim:

for_each(v.begin(),v.end(), [](int i){ cout << i << endl;});

A resposta do desafio foi com o uso da função lambda sort.

sort

A função segue o mesmo formato, mas com uma modificação nos parâmetros:

sort(v.begin(), v.end(), [](const int& a, const int& b){ return a > b;});

Mas não pára por aí. Temos outras funções lambdas que facilitam a vida na hora de programar. A próxima é a find_if, para encontrar o primeiro número maior que 3, por exemplo:

#include <stdlib.h>
#include <bits/stdc++.h>

using namespace std;

void printVector(vector<int> v){
    for_each(v.begin(), v.end(), [](int i) { std::cout << i << endl; });
    cout << endl;
}


int main(){
    vector <int> v {4,1,4,3,4,1,5,7};

    cout << "Original:" << endl;
    printVector(v);

    cout << " maior que 3: " << endl;
    vector<int>::iterator result = find_if(v.begin(), v.end(), [](int i){ return i>3;});    
    cout << "primeiro maior que 3: " << *result << endl;
}

Para fazer os exemplos utilizei o notebook. Não é necessário subir para o Arduino ou outro embarcado. Se fizer no Raspberry, melhor ainda, mas em um Linux qualquer você pode seguir o mesmo processo que eu:

funções lambda

Ou então crie um projeto em qualquer plataforma utilizando Codeblocks, QtCreator ou VS Code.

accumulate

Essa é uma das mais interessantes funções lambda, que acumula o resultado na base da função. Repare que aqui temos um pequeno diferencial; um terceiro argumento (1):

#include <stdlib.h>
#include <bits/stdc++.h>

using namespace std;

int main(){
    int values[15] = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};

    int acumulado = accumulate(values, values + 10, 1, [](int i, int j){return i * j;});
    cout << "acumulado:  " << acumulado << endl;
}

O resultado:

funções lambda - accumulate

unique

Para remover elementos duplicados, nada melhor! Primeiro fazemos o sort, então tendo já alinhados os elementos repetidos fazemos a remoção com unique. Nesse caso teremos 2 linhas para a resolução:

#include <stdlib.h>

#include <bits/stdc++.h>

using namespace std;

void printVector(vector<int> v){

    for_each(v.begin(), v.end(), [](int i) { std::cout << i << endl; });

    cout << endl;

}

int main(){

    vector <int> v {4,1,4,3,4,1,5,7};

    sort(v.begin(), v.end(), [](const int& a, const int& b){ return a > b;});

    vector<int>::iterator unicos = unique(v.begin(), v.end(), [](int a, int b){ return (a == b);});  
    printVector(v);

}

E por fim, um “tiro de canhão”, mas é válido.

Função em variável

Podemos acessar uma função armazenada em uma variável. Há outros modos mais simples de calcular o quadrado, mas não deixa de ser interessante:

#include <stdlib.h>
#include <bits/stdc++.h>

using namespace std;

int main(){

    auto square = [](int i){ return i*i;}; 
    cout << "Quadrado de 9: " << square(9) << endl;
}

Com esses recursos dá pra aumentar um pouco mais o prazer de programar, deixando por vezes o código mais elegante e com mais conceitos.

Até a próxima!