Manual
do
Maker
.
com
E no Desafio maker 03 temos mais uma vez uma resposta certa, e mais uma vez do Ricardo Amaral. Ele disse que pesquisou, não tem intimidade com o recurso, mas funcionou. Bom, além de funcionar era exatamente o recurso que deveria utilizar; uma função lambda, da qual discorro em seguida. Mais importante do que saber na ponta da língua é saber pesquisar, porque não detemos todo o conhecimento do mundo, mas sabendo pesquisar chegamos a uma solução. Parabéns, Ricardo.
Fico feliz em informar que também o Ruy Jorje resolveu o desafio, algumas horas depois do Ricardo.
O C++11 oferece algumas expressões de função lambda para escrever funções inline, normalmente utilizada quando a função não será reutilizada. Por exemplo, se fossemos iniciar um array longo que estivesse fora de ordem (da forma que foi proposto o desafio), melhor do que escrever uma função é utilizar o recurso da própria linguagem. O requisito de ser uma só linha também foi mais uma dica do que um requisito, mas o mais interessante é que isso levantou questões: O que é uma linha em C++?
Podemos escrever um programa inteiro em uma linha, se desejado for, portanto o ponto-e-vírgula não é uma determinação de fim de linha, até porque no loop for fazemos algo como for (uint8_t i=0; i<10;i++). Assim como no loop for, alinhar a função lambda é uma forma (não obrigatória) de determinar visualmente a resolução de uma operação em uma linha. A função lambda tem o seguinte formato:
[cláusula de captura] [parâmetros] -> tipo de retorno {definição do método}
O tipo de retorno não é obrigatório, pelo menos não na função lambda que utilizamos nesse exercício. Logo, o resultado da questão tem o seguinte formato:
sort(v.begin(), v.end(), [](const int& a, const int& b){ return a > b;});
Na cláusula utilizamos o início e o fim do objeto vector, então definimos os parâmetros que apontam para os endereços dos inteiros, seguido pela definição do método.
A cláusula:
v.begin(), v.end()
Os parâmetros:
[](const int& a, const int& b)
A definição do método:
{ return a > b;}
O ponto-e-vírgula é fundamental na linguagem, mas não obriga a pular linha, assim como o "agrupamento" de código dentro de chaves não é obrigatório em uma função quando há só uma linha:
while (true) sleep(10); //fica aqui para sempre
Adicionalmente à linha da função lambda supracitada, fiz o print utilizando também uma função lambda, portanto além do requisito, adicionei o código para visualizar o resultado. Nesse caso, ficou assim:
#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 << "Ordenado decrescente: " << endl;
sort(v.begin(), v.end(), [](const int& a, const int& b){ return a > b;});
printVector(v);
}
Apesar de visualmente não ser muito agradável, separando a função em três partes como exemplificado mais acima, fica mais fácil de guardar o formato da declaração e assim podemos reproduzir com fluidez a chamada de uma função lambda.
No próximo artigo vou mostrar mais funções lambda que facilitam na hora de escrever um código rapidamente. Espero que tenham gostado do desafio. Nos comentários feitos nos grupos de facebook percebi uma agradável interação da galera, gostei bastante e espero que continue assim.
Esse artigo é um oferecimento Baú da Eletrônica, mais um dos grandes nomes em embarcados e eletrônicos, já bastante conhecido pelos makers. Dê uma passada na loja e confira os produtos!
Até a próxima!
Inscreva-se no nosso canal Manual do Maker no YouTube.
Também estamos no Instagram.
Autor do blog "Do bit Ao Byte / Manual do Maker".
Viciado em embarcados desde 2006.
LinuxUser 158.760, desde 1997.