Instituto Federal de Mato Grosso do SulSetembro/2021

05. Higher-order Functions
Algoritmos 2
Prof. Rodrigo Duran
Nesta aula vamos:
-
O que são e como utilizar Higher-order Functions (Funções de Alta Ordem)
Vamos definir o que são Higher-order Functions e como utilizar as funções de alta ordem mais utilizadas em JavaScript.
Higher-order Functions (HoF)
Funções (até agora)
Os programas desenvolvidos até agora na disciplina fazem uso extensivo de funções, sejam elas já prontas (bibliotecas ou padrão da linguagem) ou funções definidas por nós mesmos.
Para chamar uma função basta entender corretamente os seus parâmetros...
console.log("Hello World!")
meuarray.slice(2)
meuarray.pop()
Funções (até agora)
Ou podemos definir nossas próprias funções e posteriormente chamá-las
const dobro = function(valor){
return 2*valor
}
console.log(dobro(2))
console.log(dobro(4))
Visualizando Funções
Funções (uma nova sintaxe)
A partir do padrão ECMAScript 6 é possível definir funcões com uma sintaxe mais compacta, chamada de Arrow Function.Arrow functions não substituem completamente a forma tradicional de definição de funções. Veja as restrições.
let dobro_f = function (valor){
return 2*valor
}
let dobro_a = valor => 2*valor
console.log(dobro_f(2))
console.log(dobro_a(2))
As arrow functions também podem ter mais de um parâmetro...
const soma_f = function (valor, adicionar){
return valor + adicionar
}
const soma_a = (valor, adicionar) => valor + adicionar
console.log(soma_f(1,3))
console.log(soma_a(1,3))
const soNegativaIndicePar = function (valor, indice){
if (indice % 2 == 0){
return (valor * -1)
}
else{
return valor
}
}
const snip = (valor, indice) => {
if (indice % 2 == 0){
return valor*-1
}
else{
return valor
}
}
QUIZ!
Qual é a equivalente à função quadrado usando arrow functions?
Acesse o link do exercício
let quadrado = function (n){
return n*n;
}
let quad = ______________________
QUIZ!
Escreva uma função, utilizando arrow functions que retorne o valor inicial (ini) multiplicado por um acréscimo (ac).
Acesse o link do exercício
multi(10,2)
//20
multi(2,2)
//4
QUIZ!
Escreva uma função, utilizando arrow functions, que adiciona +1 se o valor passado como parâmetro for positivo e adiciona +2 se o número for negativo
Acesse o link do exercício
adiciona(-2)
//0
adiciona(1)
//2
Higher-order Functions
Higher-order Functions (HoF) são funções que operam em outras funções: HoF tomam outras funções como parâmetros ou as retornam. Em JavaScript, funções são cidadãos de primeira classe (First-class citzens)First-class functions são funcões que são tratadas como uma outra variável qualquer: podem ser passadas como um argumento para outras funções, pode ser retornada por outra função e pode ser atribuída como um valor a uma variável.
const dobro = function(valor){
return 2*valor
}
const quadrado = function(valor){
return valor*valor
}
const negativo = function(valor){
return -1 * valor
}
const matFunc = function(valor, func){
return func(valor)
}
console.log(matFunc(3, dobro))
console.log(matFunc(3, quadrado))
console.log(matFunc(3, negativo))
Visualizando HoF
As funções Super Poderosas!
Map Filter Reduce
Repetição Implícita
Arrays em JavaScript possuem métodos pré-definidos que atuam em cada elemento do array.
Cada método age de uma forma diferente, mas map, filter e reduce são formas de repetição implícita.
Esses métodos tomam como parâmetro uma função que vai ditar "o que será feito" com cada elemento do array.
MAP

Map
Map transforma cada elemento do array de acordo com a função usada como parâmetro. O resultado do map é um novo array com os valores transformados de cada elemento.
const dobro = function(n){
return 2*n
}
const quadrado = function(n){
return n*n
}
let numeros = [1,2,3,4,5]
let num_dobro = numeros.map(dobro)
console.log(num_dobro)
let num_quad = numeros.map(quadrado)
console.log(num_quad)
Visualizando Map
Map
Map também aceita um segundo parâmetro (além de cada elemento do array) o qual corresponde ao índice do elemento no array.
const dobro = function(val, index){
if (index != 0){
return val*2
}
else{
return val
}
}
let valores = [1,3,5,7,9];
let nv = valores.map(dobro)
console.log(nv)
Visualizando Map
QUIZ!
Qual é a saída (impressa no console) após a execução do programa abaixo?
let inversa = function(valor){
return -1 * valor
}
let coordenadas = [-0.3, -1.7, 4.2, 5.1, -2.0, 13.3, 5]
console.log(coordenadas.map(inversa))
QUIZ!
Canais RGB

O programa no exercício está incompleto. Cada pixel em uma imagem é dado por 3 valores (Vermelho, Verde, Azul) e Transparência (alpha). O objetivo do código do exercício é retornar o inverso de cada pixel em uma imagem. Para inverter cada canal da imagem, basta subtrair 255 do canal de cor. Isso deve ser feito para todos os canais, exceto o alpha.
Dica : para verificar se um número qualquer é múltiplo de 4, base que o resto da sua divisão inteira por 4 seja zero. A função módulo (%) em JavaScript calcula o resto da divisão inteira de um número por outro
Acesse o link do exercício
FILTER

Filter
Filter testa se cada elemento do array satisfaz a função parâmetro. Para cada elemento cujo o resultado da função é TRUE, esse elemento é inserido no novo array de resposta. Portanto, filter retorna um novo array contendo apenas os elementos que satisfazem a função.
const negativo = function(n){
return n > 0
}
let numeros = [-1,0,-2,2,-3,5, -4]
let positivos = numeros.filter(negativo)
console.log(positivos)
Visualizando Filter
Filter
Filtrando todas as palavras que contém uma determinada frase (String)
let fruits = ['maca', 'banana', 'uva', 'manga', 'laranja']
function filtrarItems(arr, frase) {
return arr.filter( el => el.indexOf(frase) >= 0)
}
console.log(filtrarItems(fruits, 'ma'))
console.log(filtrarItems(fruits, 'an'))
Visualizando Filter
QUIZ!
Qual é a saída (impressa no console) após a execução do programa abaixo?
Acesse o link do exercício (Google Forms)
let bandas = ["The Beatles", "Rolling Stones", "Pink Floyd", "Led Zeppelin", "Queen", "The Beach Boys"]
let sm = bandas.filter( nome => nome.length > 12)
console.log(sm)
QUIZ!
Considere que exista um array com as idades de todos os alunos da disciplina de Algoritmos 2 (ou seja, todos os estudantes da turma INFO 2). Escreva um programa que filtre apenas os estudantes maiores de 14 anos.
Acesse o link do exercício
REDUCE

Reduce
Reduce, diferentemente de map e filter, não retorna (necessariamente) um array como resultado. Reduce retorna um único elemento resultante da aplicação da função nos elementos do array. Para tanto, reduce introduz um novo parâmetro que serve como acumulador para o resultado parcial.
let somador = function (acumulador, valor) {
return acumulador + valor
}
let numeros = [2 , 4 , 6, 8, 10]
console.log(numeros.reduce(somador, 0))
Visualizando Reduce
O Poder da Composição
Encadeando HoF e tornando seu código muito mais enxuto (e legível)!
Compondo HoF
Uma grande vantagem oferecida por HoF é a composição. Como map e filter retornam um array, podemos imediatamente encadear uma outra HoF a partir do resultado da anterior.
Dessa forma, nós podemos criar funcões menores que gerenciam um (ou poucos) objetivos. Podemos compor funcões mais complexas utilizando várias funcões menores.
Esta técnica pode reduzir o número de bugs e fazer com que o código seja mais fácil de ser compreendido. Você pode compor quantas funções achar necessário.
const negativo = function(n){
return n > 0
}
let soma = function (n, acc){
return acc + n
}
let numeros = [11,-4, -3, -8, 10, -3, 4, -7, 9, -11]
let s = numeros.filter(negativos).reduce(soma)
console.log(s)
Apenas items contendo a substring "la" e com tamanho superior a 5 caracteres
let contem_frase = function (elem) {
return elem.indexOf("la") >= 0
}
let maior_que = function (elem){
return elem.length > 5
}
let produtos = ["caderno", "lapis", "borracha", "lapiseira", "papel"]
let procura = produtos.filter(contem_frase).filter(maior_que)
console.log(procura)