So I have the following code, from which I expect the x function to return null after being called 3 times but it keeps returning the the same function:
const repeat = (n, tailFn) => {
for (let i = 0; i < n; i++) {
tailFn = () => tailFn;
}
return tailFn;
};
const x = repeat(2, x => null);
console.log(x()); // function tailFn() { return _tailFn }
console.log(x()()); // function tailFn() { return _tailFn }
console.log(x()()()()()()); // function tailFn() { return _tailFn }
What am I doing wrong? See it on CodePen.
Your function just assigns () => tailFn to tailFn three times and then returns it. Instead, you should return a function which returns repeat(n - 1, tailFn) if n is not 0, and tailFn otherwise.
const repeat = (n, tailFn) => {
return n !== 0 ? () => repeat(n - 1, tailFn) : tailFn;
};
const x = repeat(2, x => null);
console.log(x()); // () => repeat(n - 1, tailFn)
console.log(x()()); // x => null
console.log(x()()()); // null
You have created a function that ALWAYS returns itself,
tailFn=()=>tailFn;
actually the loop is meaningless.Its behavior is similar to a recursive function without a base case.
Related
I need a function limitCalls (fn, maxCalls) that takes a function fn and returns a new function that can be called no more than the number of times specified in maxCalls. Test example:
it('limitCalls', () => {
const makeIncrement = () => {
let count = 0;
return () => {
count += 1;
return count;
};
};
const limitedIncrementA = limitCalls(makeIncrement(), 3);
expect(limitedIncrementA()).toBe(1);
expect(limitedIncrementA()).toBe(2);
expect(limitedIncrementA()).toBe(3);
expect(limitedIncrementA()).toBe(undefined);
expect(limitedIncrementA()).toBe(undefined);
const limitedIncrementB = limitCalls(makeIncrement(), 1);
expect(limitedIncrementB()).toBe(1);
expect(limitedIncrementB()).toBe(undefined);
expect(limitedIncrementB()).toBe(undefined);
});
I have:
var calls = 0;
export default function limitCalls(fn, maxCalls) {
if (calls >= maxCalls) {
return undefined;
}
calls += 1;
return fn();
}
And error is limitedIncrementA is not a function. Help me please to realise it.
Instead of conditionally returning a function, always return a function that conditionally executes the fn callback:
function limitCalls(fn, maxCalls) {
let count = 0;
return function(...args) {
return count++ < maxCalls ? fn(...args) : undefined;
}
}
const limited = limitCalls(console.log, 3);
limited('one');
limited('two');
limited('three');
limited('four');
In this snippet, limitedIncrementA isn't indeed a function. See this:
/* You're calling makeIncrement,
so you're passing its return to 'limitCalls'
*/
const limitedIncrementA = limitCalls(makeIncrement(), 3);
/* Here, considering that makeIncrement exists,
you're passing a reference to this functions,
which can be called inside 'limitCalls'
*/
const limitedIncrementB = limitCalls(makeIncrement, 3);
So, supposing that makeIncrement returns 1, 2, 3, ..., your current code is equivalent to:
limitCalls(1, 3);
Let's say I have a function called f that takes an integer argument called x and returns an integer. I also have an integer n that says how many times the function must call itself. So for example if my function call looks like this f(x) when n = 1, then it would look like this f(f(f(x))) when n = 3. How could something like that look in my example bellow:
function succ(n) {
return function (f, x) {
return f(x);
};
}
You could loop inside the inner function:
for(let i = 0; i < n; i++) x = f(x);
return x;
or alternatively let your function call itself:
return n > 0 ? succ(n - 1)(f, f(x)) : x;
We can express this algorithm corecursively. Corecursion builds its result on the way forward from the starting point:
const iterate = f => x =>
[x, () => iterate(f) (f(x))];
const main = iterate(x => x * 2) (1);
console.log(
main[1] () [1] () [1] () [1] () [1] () [1] () [1] () [1] () [0]); // 256
This is just a proof of concept but not what we actually want. How can we avoid the clunky interface? We can use a Proxy to make the non-argument function implicit. It is basically the same mechanism as with lazy property getters. Additionally we don't want to access values from the stream manually but with a function for convenience:
class ThunkProxy {
constructor(f) {
this.memo = undefined;
}
get(g, k) {
if (this.memo === undefined)
this.memo = g();
if (k === THUNK)
return true;
else if (k === Symbol.toPrimitive)
return () => this.memo;
else if (k === "valueOf")
return () => this.memo;
else return this.memo[k];
}
}
const THUNK = "thunk";
const thunk = f =>
new Proxy(f, new ThunkProxy(f));
const iterate = f => x =>
[x, thunk(() => iterate(f) (f(x)))];
const takeNth = n => ([head, tail]) =>
n === 0
? head
: takeNth(n - 1) (tail);
const main = iterate(x => x * 2) (1);
console.log(
main[1] [1] [1] [1] [1] [1] [1] [1] [0]); // 256
console.log(
takeNth(16) (main)); // 65536
You could build a times high order function and use it to wrap other functions...
const times = (fn, n) => (...args) => {
if (!n) { return; }
fn(...args);
return times(fn, n - 1)(...args);
}
const log10 = times(console.log, 10);
log10('hello');
As a toy example lets say we have this function and its usage:
const map = (f = n => n + 1) => (lst = [1,2,3]) => {
if(lst.length === 0)
return [];
else
return [f(...lst.splice(0,1)), ...map(f)(lst)];
}
const inc = n => n + 1;
const map_inc = map(inc);
map_inc([1,2,3]) // => (produces) [2,3,4]
Inside of the curried function map I am using "recursion" by calling map(f)(lst).
The example above rebuilds the function before it can be called.
Is it possible to do this recursion without rebuilding the function?
I know of this way:
y = (f = (f, ...args) => [...args],
...args) => f(f, ...args);
const map = (mapper = n => n + 1) => (self = mapper, lst = [1,2,3]) => {
if(lst.length === 0)
return [];
else
return [mapper(...lst.splice(0,1)), ...self(self, lst)];
}
const inc = n => n + 1;
const map_inc = (...args) => y(map(inc), ...args);
map_inc([1,2,3]) // => (produces) [2,3,4]
I do not really like how this requires the passing of the function to itself.
Can this be done without the y function and without passing the function to itself? Can this be done in a more point-free style?
If I'm understanding your question correctly, you can't return named arrow functions, but you can return a named regular function and call it recursively like this:
const reducer = k => function recurse(a, item) {
//...
const s_res = _.split(item, k, 1);
return recurse(a.withMutations(a => {
a.push(s_res[0]);
let a_element = document.createElement('a');
a_element.setAttribute('href', '#');
a_element.addEventListener('click', () => display_gen_element(k, obj));
a.push(a_element);
}), s_res[1]);
};
P.S. For the sake of readability please don't use one-letter variable names unless it's blindingly obvious what they're for, e.g. a counter in a for loop, etc.
If your purpose was remove the need to pass self to itself
...self(self, lst)
You can do this by adding 1 more function named recursor
const map = (mapper = n => n + 1) => (lst = [1, 2, 3]) => {
const recursor = lst => {
if (lst.length === 0) return [];
else return [mapper(...lst.splice(0, 1)), ...recursor(lst)];
};
return recursor(lst);
};
const inc = n => n + 1;
const map_inc = map(inc);
console.log(map_inc([1, 2, 3])); // => (produces) [2,3,4]
You didn't need the y combinator-like function called y at all.
recursor has mapper in its closure
I have a function like that:
function intiFun(initValue) {
const firstResult = firstFun(initValue);
const secondResult = secondFun(firstResult);
const thirdResult = thirddFun(secondResult);
const fourthResult = fourthFun(thirdResult);
return fourthResult;
}
but i want to write it better. and i dont want to save value from each function as variable.
is there any solution to to call functions with out save old value
like rxjs or somthing like that:
function intiFun(initValue) {
return firstFun(initValue).secondFun().thirddFun().fourthFun();
}
or more better like that:
function intiFun(initValue) {
return firstFun(initValue)
.secondFun(secondInput)
.thirddFun(secondInput)
.fourthFun(secondInput)
}
function secondFun(value, secondInput) {
return ...;
}
...
or some liberally to do that (maybe lodash)
My guess is you're looking for function composition: we can construct the composite function from an array of functions in JavaScript using for example reduce (with the initial value being the identity function (v) => v:
const composeAll = (functions) => functions.reduce(
(composition, f) =>
((v) => f(composition(v))),
(v) => v
);
const firstFun = (s) => `${s}a`;
const secondFun = (s) => `${s}b`;
const thirdFun = (s) => `${s}c`;
const fourthFun = (s) => `${s}d`;
const intiFun = composeAll([firstFun, secondFun, thirdFun, fourthFun]);
console.log(intiFun(''));
OUTPUT:
abcd
NOTES:
As you can see, composeAll creates a chained function call by wrapping each function f in an arrow function which takes a value v, executes it on the composite function constructed from the preceding functions in the array and finally passes the result to f.
You can convince yourself that the construction is correct by induction over the array length: if we define the composition of an empty list of functions to be the identity function then
in the base case (for a singleton array [f] with length 1) the result is
(v) => f((v => v)(v)) === (v) => f(v)
in the step case (for an array with length n) assume the function obtained for the n-1 preceding functions in the array was correctly constructed (let this be g), then the result is
(v) => f_n(g(v)) === (v) => f_n(f_n-1(...(f_0(v))...))
pipe, manual currying & partial application to the rescue:
const pipe = funs => x =>
funs.reduce ((o, fun) => fun (o), x)
const f = x => x + 1
const g = x => y => x + y * 2
const h = x => x * x
const i = x => y => z => x + y / z + 3
const j = x => x + 5
const init = pipe ([
f
,g (4)
,h
,i (10) (33)
,j
])
const input = 1
const output = init (input)
console.log (output)
You can do something like this
const firstFun = x => x + 1;
const secondFun = x => x + 1;
const thirdFun = x => x + 1;
const fourthFun = x => x + 1;
const pipe = (...functions) => x => functions.reduce((x, f) => f(x), x);
const initFun = pipe(firstFun, secondFun, thirdFun, fourthFun);
console.log(initFun(3));
const firstFun = x => { /* return ... */ };
const secondFun = x => { /* return ... */ };
const thirdFun = x => { /* return ... */ };
const fourthFun = x => { /* return ... */ };
const callAll= (value, ...functions) => {
functions.forEach(fn => value = fn(value));
retrun value;
}
const result = callAll(3, firstFun, secondFun, thirdFun, fourthFun);
console.log(result);
The result you're looking for can be achieved using reduce.
let log = (head, ...args) => { console.log('log:', head, ...args); return head },
firstFun = (str, ...args) => log(str, ...args) + ' firstFun',
secondFun = (str, ...args) => log(str, ...args) + ' secondFun',
thirddFun = (str, ...args) => log(str, ...args) + ' thirddFun',
fourthFun = (str, ...args) => log(str, ...args) + ' fourthFun';
function initFun(initValue) {
let functions = [
[firstFun],
[secondFun, 'extra argument'],
[thirddFun],
[fourthFun, "I'm here too"],
];
return functions.reduce((result, [fn, ...args]) => fn(result, ...args), initValue);
}
console.log( 'result: ' + initFun('foo bar') );
Keep in mind that I log the incomming arguments of the methods, not the resulting value. This means that for example secondFun (log: foo bar firstFun extra argument) has the argument 'foo bar firstFun' and 'extra argument'. But you only see the added string 'secondFun' when thirdFun is called (since it is given as the argument).
function initFun(initValue) {
return fourthFun(thirddFun(secondFun(firstFun(initValue))));
}
Alternatively, convert your function into promises:
function initFun(initValue) {
return firstFun(initValue)
.then(secondFun)
.then(thirddFun)
.then(fourthFun);
}
Bad Method — See Below
If you want something like a.firstFunc().secondFunc().thirdFunc().fourthFunc(), you should define those functions to Object.prototype (or Number.prototype, String.prototype, etc.):
Object.prototype.firstFunc = function() {
var value = this;
// ...
return something;
};
Object.prototype.secondFunc = function() {
var value = this;
// ...
return something;
};
Object.prototype.thirdFunc = function() {
var value = this;
// ...
return something;
};
Object.prototype.fourthFunc = function() {
var value = this;
// ...
return something;
};
P.S. "Function" is normally shortened to "func" but not "fun".
Update
If you want something like myObject(a).firstFunc().secondFunc().thirdFunc().fourthFunc(), you should:
var myObject = function(value) {
this.value = value;
};
myObject.prototype.firstFunc = function() {
var value = this.value;
// ...
return something;
};
myObject.prototype.secondFunc = function() {
var value = this.value;
// ...
return something;
};
myObject.prototype.thirdFunc = function() {
var value = this.value;
// ...
return something;
};
myObject.prototype.fourthFunc = function() {
var value = this.value;
// ...
return something;
};
I need an explanation to as what has been done in the gridFull state of this constructor.Being new to javascript, I couldn't get this line of code.
constructor() {
super();
this.speed = 100;
this.rows = 30;
this.cols = 50;
this.state = {
generation: 0,
gridFull: Array(this.rows).fill().map(() => Array(this.cols).fill(false))// this line of code is unclear to me
}
Let's break down the line:
Array(this.rows)
this creates an array with this.rows many rows. In this case, 30.
.fill()
fills the array with undefined values (more info on fill function)
.map(callbackFunction)
this returns a new array with each value being transformed by the function. Since you have an array of undefined, you'll call the function as you would the following callbackFunction(undefined).
Now for the callback function:
() => Array(this.cols).fill(false);
This function takes no parameters (hence ()), and returns an Array with this.cols size (which is 50), all containing false.
tl;dr:
So, you're essentially creating a 30x50 matrix filled with false on each element.
EDIT:
explaining arrow functions:
(list-of-parameters) => (function block | return value)
To explain using examples, we can transform function one() { return 1; } into () => 1;.
Or function times(a, b) { return a * b;} into (a, b) => a * b;
Or another:
let x = 0;
function foo(y) {
const returnValue = (x++) * y;
return returnValue;
}
to
let x = 0;
const foo = (y) => {
const returnValue = (x++) * y;
return returnValue;
}
EDIT2:
More ways to accomplish the same result:
let result = Array(rowCount).fill();
for (let i = 0; I < rowCount; i++) {
result[i] = Array(colCount).fill(false);
}
Another:
const line = Array(colCount).fill(false);
const result = Array(rowCount).fill().map(() => [...line]);
And another:
const line = Array(colCount).fill(false);
const result = [];
for (let idx = 0; idx < rowCount; idx++) {
result.push([...line]);
}
Or you can create your own "matrix creator":
function matrix(row, col) {
const data = Array(row * col).fill(false);
const findIdx = (x, y) => y * col + x;
return {
get: (x, y) => data[findIdx(x,y)],
set: (x, y, value) => {
data[findIdx(x,y)] = value
return data[findIdx(x,y);
},
};
}