Desafío de Nombres y Apellidos

RMAG news

El siguiente es un pequeño ejercicio encontrado en el curso de Haskell
disponible en la Universidad de Helsinki.

Desafío

Dado una lista de nombres y apellidos:

Nombres: [“Eva”, “Mike”]

Apellidos: [“Smith”, “Wood”, “Odd”]

Retornar una lista cuyos elementos sean solo de personas con largo par.

Ejemplo de Retorno

[“EvaSmith”, “EvaOdd”, “MikeWood”]

Solución en Haskell

Haskell permite pattern matching y list comprehensions.

[whole | first <- [“Eva”, “Mike”],
last <- [“Smith”, “Wood”, “Odd”],
let whole = first ++ last,
even (length whole)]

Solución en Elixir

Si bien la solución en Elixir no es tan corta como en Haskell
es igual de elegante.

require Integer

for first <- ~w[Eva Mike],
last <- ~w[Smith Wood Odd],
name <- [first <> last],
name
|> String.length()
|> Integer.is_even(), do: name

Para esto utilizamos las características de for comprehensions.

https://elixirschool.com/en/lessons/basics/comprehensions

Solución en Javascript

David de Javascript Chile nos escribe una solución en versión
imperativa y declarativa utilizando Javascript.

Imperativa

const nombres = [Eva, Mike];
const apellidos = [Smith, Wood, Odd];

const output = [];

for(let i = 0; i < nombres.length; i++){
for(let j = 0; j < apellidos.length; j++){
const fullName = `${nombres[i]}${apellidos[j]}`;
if(fullName.length % 2 == 0){
output.push(fullName);
}
}
}

Declarativa

const nombres = [Eva, Mike];
const apellidos = [Smith, Wood, Odd];

const output = nombres.flatMap(n =>
apellidos.map(a => `${n}${a}`)
)
.filter(fullName => fullName.length % 2 == 0);

Elixir

La versión declarativa de Javascript la podríamos emular en Elixir de la siguiente
forma:

~w[Eva Mike]
|> Enum.flat_map(fn first ->
~w[Smith Wood Odd]
|> Enum.map(fn last ->
first <> last
end)
end)
|> Enum.filter(&
&1
|> String.length()
|> Integer.is_even()
)

Aunque no es tan elegante como usar for comprehensions.

¿En qué otros lenguajes puedes solucionar el desafío?