Reputation: 15
This code returns multiple of 5. I am trying to do it in a functional way. Is it functional?
function Mul(start,array,Arr)
{
Arr[start]=array[start]*5;
if(start>array.length-2){
return Arr;
}
return Mul(start+1,array,Arr);
}
var numbers =[1,2,3,4,5,6,7,8,9,10];
var Arr=[];
I am passing an empty array and storing values in it.
console.log("table ", Mul(0,numbers,Arr));
Upvotes: 1
Views: 268
Reputation: 14179
Let's not forget that also recursion comes in handy here!
const multipleOf = (factor) => (length) => {
if (!length) { return []; }
return [
...multipleOf(factor)(length - 1),
length * factor
];
};
const by5 = multipleOf(5);
const by2 = multipleOf(2);
console.log(
by5(10),
);
console.log(
by2(50),
);
Upvotes: 0
Reputation: 18901
Your initial attempt wouldn't qualify as functional since it modifies its original input.
This isn't ideal because in addition to keeping track of the execution flow of a program you also need to worry about the data. Here's a contrived example:
const last = arr => arr.pop();
const sum = ([a, b]) => a + b;
const x = [4, 2];
const y = [4, 2];
// Works as expected
sum(x); //=> 6
last(x); //=> 2
// Bug!
last(y); //=> 2
sum(y); //=> NaN
The issue here is that Array#pop
modifies the array. We can observe that for the same input the order of execution now matters. This is unnecessary, leads to unstable programs and create bugs that while trivial to fix are sometimes very hard to spot.
If your intention is to multiply all elements in your array with 5
then the simplest solution yet fully functional is to do xs.map(x => x * 5)
.
In functional programming there's also a function called unfold
that generates a list by applying a function on a value until a condition is met. It would look like this:
unfold(mult5, 1); // we start with 1 until 10 and we multiply by 5 along the way.
//=> [5, 10, 15, 20, 25, 30, 35, 40, 45, 50]
But we don't need to go into these details if the boundaries are known in advance. i.e. you need the first n multiple of 5
.
Let's "allocate" 10 spots for our multiples of five:
const xs = Array(10);
//=> An array of 10 empty values
Warning: you cannot map such an array!
const ys = xs.map(x => x * 5);
//=> Still an array of 10 empty values!
You need to use Array.from
:
const ys = Array.from(xs, (_, i) => (i + 1) * 5);
//=> [5, 10, 15, 20, 25, 30, 35, 40, 45, 50]
Upvotes: 0
Reputation: 370819
It's not functional, since you're mutating the argument.
A more functional method would be to use the built-in .map
function to transform each element of the array:
const mult5 = arr => arr.map(item => item * 5);
const Mul = (start, input) => input.slice(0, start).concat(mult5(input.slice(start)));
console.log("table ", Mul(0, [1,2,3,4,5,6,7,8,9,10]));
(though, that admittedly isn't perfectly functional either, due to the console.log
, which is a side-effect)
If you always transform the whole array, there's no need for start
:
const Mul = arr => arr.map(item => item * 5);
console.log("table ", Mul([1,2,3,4,5,6,7,8,9,10]));
Upvotes: 2