Assíncrono e Single-threaded JavaScript?
JavaScript é uma linguagem single-threaded e, ao mesmo tempo, também non-blocking, assíncrona e concorrente. Este artigo explica-lhe como isso acontece.
Confira a terceira parte da nossa série de artigos Poder da programação funcional no JavaScript. Desta vez, nosso especialista em JavaScript explica mais sobre Functor e Monad Maybe.
Muitas vezes, é difícil manter os dados inalteráveis. O padrão de envolver os dados num contentor vem em seu socorro. Protege os valores para que o seu manuseamento seja seguro, excluindo os efeitos secundários.
Se é novo aqui, não deixe de ver as minhas duas últimas partes sobre programação funcional no blogue The Codest:
Não tem uma lógica complexa. A sua principal tarefa é envolver o contexto e executar as funções que recebe do exterior. Cada vez que o valor muda, uma nova instância do contentor é reembalada e devolvida. Ao chamar o mapa que executa uma ação específica, devolve uma nova instância de contentor com o valor devolvido pela função passada, mantendo o princípio de não modificabilidade.
const Functor = value => ({
map: fn => Functor(fn(value)),
cadeia: fn => fn(valor),
of: () => valor
});
mapa - útil quando se pretende alterar o estado de um valor num contentor mas não se pretende devolvê-lo ainda.
cadeia - utilizado se quiser passar um valor para uma função sem modificar o estado do contentor. Geralmente no final de mapa chamadas.
de - devolver o valor atual
const randomInt = (max) => Math.floor(Math.random() * (max + 1))
const randomNumber = randomInt(200) // devolve um número entre 0 e 200
decrease(randomNumber) // devolve (número entre 0 e 200) - 1
const randomIntWrapper = (max) =>
Functor(max)
.map(increase) // max + 1
.map(multiplyBy(Math.random())) // Math.random() * (max + 1)
.map(Math.floor) // Math.floor(Math.random() * (max + 1))
const randomNumber = randomIntWrapper(200)
randomNumber.of() // devolve um número entre 0 e 200
randomNumber.chain(decrease) // devolve (número entre 0 e 200) - 1
Por vezes, para além das funções que accionam o novo estado do valor, é necessária uma lógica adicional oculta no contentor. É aqui que a mônada se torna útil, pois é uma extensão de functor. Pode, por exemplo, decidir o que deve acontecer quando o valor tem um determinado valor ou qual o caminho que as próximas acções devem seguir.
A mónada talvez resolva o problema dos valores que retornam não verdadeiros. Quando isso acontece, as mapa são ignoradas, mas permite-lhe devolver uma alternativa chamando o getOr método. Permite-lhe evitar a utilização de operadores if / else, que são populares em imperativo programação. Esta mónada é constituída por três contentores:
Nada - é executado quando um valor que não é verdadeiro cai no contentor ou filtro devolve falso. É utilizado para simular a execução de uma função. Isto significa que este contentor recebe a função mas não a executa.
Só - este é o contentor principal que executa todas as funções, mas se o valor mudar para um valor falso ou filtro retorna falso, ele passará para o método Nada contentor.
Talvez - Pego no valor inicial e decido qual o contentor a chamar no início.
const Just = value => ({
map: fn => Maybe(fn(value)),
chain: fn => fn(value),
of: () => value,
getOr: () => valor,
filtro: fn => fn(valor) ? Just(value) : Nothing(),
type: 'just'
});
const Nothing = () => ({
map: fn => Nothing(),
chain: fn => fn(),
of: () => Nothing(),
getOr: substitute => substitute,
filter: () => Nothing(),
type: 'nothing'
});
const Maybe = valor =>
value === null || value === undefined || value.type === 'nothing'
? Nada()
: Just(value)

Agora vamos construir o exemplo anterior sobre a condição. Se max for maior que zero, a função será executada. Caso contrário, retornará 0.
const randomInt = (max) => {
if(max > 0) {
return Math.floor(Math.random() * (max + 1))
} else {
return 0
}
}
const bookMiddlePage = 200
const randomPage = randomInt(10) || bookMiddlePage // devolve aleatório
const randomPage = randomInt(-10) || bookMiddlePage // devolve 200
const randomIntWrapper = (max) =>
Talvez(max)
.filter(max => max > 0) // o valor false ignora outras chamadas
.map(increase)
.map(multiplyBy(Math.random()))
.map(Math.floor)
const bookMiddlePage = 200
// Apenas contentor
const randomPage = randomIntWrapper(10).getOr(bookMiddlePage) // retorna aleatório
// Contentor de nada
const randomPage = randomIntWrapper(-10).getOr(bookMiddlePage) // devolve 200