How do I read and interpret the following line of a function:
const canUser = (permission) => (permissions) => (guideSlug) => {
This is the full function:
const canUser = (permission) => (permissions) => (guideSlug) => {
if (!permissions) return false;
const globalPermissions = permissions['*'] || {};
const guidePermissions = permissions[guideSlug] || {};
return globalPermissions[permission] || guidePermissions[permission] || false;
};
Edit
If I have an object like this:
export const checks = {
canInvite: canUser('invite'),
}
I'm importing canInvite into my component and then running that function, giving it a guideSlug (string) to run the function. It works and checks out, I'm just not entirely sure how to understand what this does from the const canUser function definition
Any clarity here would be helpful. Thanks!
const foo = function(x) { return x + 1 } can be loosely written as const foo = x => x + 1. The latter is called an arrow function
So
const canUser = (permission) => (permissions) => (guideSlug) => {
if (!permissions) return false;
const globalPermissions = permissions['*'] || {};
const guidePermissions = permissions[guideSlug] || {};
return globalPermissions[permission] || guidePermissions[permission] || false;
};
is same as
const canUser = function(permission) {
return function(permissions) {
return function (guideSlug) {
if (!permissions) return false;
const globalPermissions = permissions['*'] || {};
const guidePermissions = permissions[guideSlug] || {};
return globalPermissions[permission] || guidePermissions[permission] || false;
}
}
};
This is called partial application or currying, both are kinda same I'm not sure which is the accurate term here.
Here's a case where it's useful...
const foo = (x, y) => { /* something to be done with x and y */ }
let x = foo(a,b);
let y = foo(a,c);
let z = foo(a,d);
Here as you can see there's a lot as in the code which is kinda repetitive and less readable. Writing it in the following way solves the problem...
const foo = x => y => { /* something to be done with x and y */ }
let fooA = foo(a); // fooA is the `y => {}` function with `x = a` "partially applied"
let x = fooA(b);
let y = fooA(c);
let z = foo(a)(d); // you can still write it like this
Another advantage of such pattern is that you can pass around fooA to other function or if you want to store it in an abstraction of a like const somethingRelevantToA = { foo: foo(a), bar: "some other prop ofa" }.
Also you are reusing the logic if you want something like fooA and fooB and they have something in common like...
const foo = x => y => {
/* piece of code independent of x (this is being reused) */
/* piece of code dependent only on y or x and y both */
}
So basically instead of writing fooA and fooB separately you are writing foo and thus reusing the logic.
That piece of code can be rewritten in ES5 like this:
var canUser = function canUser(permission) {
return function (permissions) {
return function (guideSlug) {
if (!permissions) return false;
var globalPermissions = permissions['*'] || {};
var guidePermissions = permissions[guideSlug] || {};
return globalPermissions[permission] || guidePermissions[permission] || false;
};
};
};
This is called currying. Which, as state in this article, is the process of taking a function with multiple arguments and turning it into a sequence of functions each with only a single argument.
Assuming you have permissions and guideSlug defined somewhere,
var permissions = {'accounts':{'invite': true}, '*':{'home': '/'}};
var guideSlug = 'accounts';
You could call the function with:
canUser('invite')(permissions)(guideSlug)
var permissions = {'accounts':{'invite': true}, '*':{'home': '/'}};
var guideSlug = 'accounts';
var canUser = function(permission) {
return function(permissions) {
return function (guideSlug) {
if (!permissions) return false;
var globalPermissions = permissions['*'] || {};
var guidePermissions = permissions[guideSlug] || {};
console.log(globalPermissions);
console.log(guidePermissions);
return globalPermissions[permission] || guidePermissions[permission] || false;
}
}
};
console.log(canUser('invite')(permissions)(guideSlug));
One thing I noticed in your example is that it calls only the first function, which means it will return a function back to checks.canInvite when you call it here:
export const checks = {
canInvite: canUser('invite'),
}
Related
I am trying handle below code and its showing
enter image description here
const toArray = props =>
(props && props.split ? props.split(',') : props || []).map(item => item.trim());
const hasField = (entity, fields) => {
if (!fields.length) {
return false;
}
for (let i = 0; i < fields.length; i + 1) {
if (entity && entity.includes(fields[i])) {
return true;
}
}
return false;
};
module.exports = (entities, query) => {
const industries = toArray(query.industries);
const technologies = toArray(query.technologies);
const maturity = toArray(query.maturity);
return entities.filter(function (entity) {
const hasTecnology = hasField(entity.industries, industries);
const hasIndustury = hasField(entity.technologies, technologies);
const hasMaturity = hasField(entity.maturity, maturity);
const condition = hasTecnology || hasIndustury || hasMaturity;
if (condition) return entity;
}, []);
};
output showing:
23:26 error Array.prototype.filter() expects a value to be returned at the end of function
array-callback-return
Line 23:26 is ==> module.exports = (entities, query) => {
Could you please check this? What I wrongly doing here?
It's just as the error says - you're not always returning a value.
The callback return value only needs to be truthy or falsey. Change
if (condition) return entity;
to
return condition;
I need the name function to be defined for use with another method further down so I need it to be dynamically named.
currently...
`use strict`;
const factory = () => () => {}
const method = factory();
method.name === undefined
&&
const factory = () => { const name = () => {}; return name }
const method = factory();
method.name === "name"
because...
`use strict`;
const factory = () => () => {}
factory() === () => {} // and () => {} is not a named method
But I want...
`use strict`;
const factory = () => () => {}
const method = factory();
method.name === "method"
this is extra description because stack overflow wants me to say more but I think that the problem is self-explanatory
Make your arrow function a traditional function:
const factory = () => function method() {}
If the name is to be dynamic, then we have to deal with the fact that a function's name property is read-only. The function definition could happen in a dynamic way (but that involves parsing), or we could create a proxy:
const factory = () => new Proxy(() => console.log("hello"), {
get(obj, prop) {
return prop === "name" ? "method" : prop;
}
});
const method = factory();
console.log(method.name);
method();
Variable name
In comments you explained that the dynamic name should be determined by the variable name (i.e. method), but:
There can be many variables referring to the same function, while a function has only one name -- so that leads to an unresolvable paradox.
Variable names only exist at parse time, not at execution time.
You can do that by creating an object with the dynamic name prop and assigning the function to that prop:
`use strict`;
const factory = s => (
{[s]: () => {}}[s]
)
const method = factory('blah');
console.log(method.name)
Does this work? You'd have to repeat the name, though, so not sure it totally gets what you're looking for
let factory = (name) => new Function(`return function ${name}() {}`)();
let method = factory("method");
method.name; // "method"
Building off of #trincot's answer, what was initially proposed is not possible.
However, here's what I went with for a sufficient alternative:
`use strict`;
// #trincot's answer
const renameFunction = (name, func) => new Proxy(func, {
get(obj, prop) {
return prop === "name" ? name : prop;
}
})
const identifyFunction = (obj) => {
if (typeof obj === "object") {
// because the object has the original defined as a property
// we can pull the name back out
const name = Object.keys(obj)[0];
const func = obj[name];
return renameFunction(name, func)
}
// if it's not an object then assume it's named and return
return obj
}
const useFooName = (foo) => {
let _foo = foo;
// only need to identify if it's an object
if (typeof _foo === "object") {
_foo = identifyFunction(foo)
}
// using both the function and its name
console.log(`${_foo.name} ${_foo()}`);
}
const factory = (func) => func;
const foo = factory(() => "bar");
useFooName(foo) // bar
useFooName({ foo }) // foo bar
This can be used dynamically as well...
`use strict`;
// #trincot's answer
const renameFunction = (name, func) => new Proxy(func, {
get(obj, prop) {
return prop === "name" ? name : prop;
}
})
const identifyFunction = (obj) => {
if (typeof obj === "object") {
// because the object has the original defined as a property
// we can pull the name back out
const name = Object.keys(obj)[0];
const func = obj[name];
return renameFunction(name, func)
}
// if it's not an object then assume it's named and return
return obj
}
// let there be a function that accepts and function bar
// and uses bar's name; for whatever reason you don't want to
// change this method
const useBarName = (bar) => `${bar.name} ${bar()}`
// let there also be an arbitrary amount of functions using this
const traditionalWay = () => {
const a = () => "b";
const c = () => "d";
const e = () => "f";
console.log([a, c, e].map(useBarName).join(" ")); // a b c d e f ...
}
// but instead of hard-coding the functions it'd be easier
// to just build a factory that did it automatically
const brokenWay = () => {
const factory = (letter) => () => letter;
const a = factory("b");
const c = factory("d");
const e = factory("f");
console.log([a, c, e].map(useBarName).join(" ")); // b d f ...
}
// so instead you can use the indentifyFunction to identify
// the anonymous methods
const newWay = () => {
const factory = (letter) => () => letter;
const a = factory("b");
const c = factory("d");
const e = factory("f");
console.log([{a}, {c}, {e}].map(identifyFunction).map(useBarName).join(" ")); // a b c d e f ...
}
traditionalWay();
brokenWay();
newWay();
This function should have two parameters: a function and a value. It should call the argument function with the value two times. If the callback function produces the same result twice, it should return the result of the function call, otherwise, it should return the string 'This function returned inconsistent results'
const checkThatTwoPlusTwoEqualsFourAMillionTimes = () => {
for(let i = 1; i <= 1000000; i++) {
if ( (2 + 2) != 4) {
console.log('Something has gone very wrong :( ');
}
}
};
const addTwo = num => num + 2;
const timeFuncRuntime = funcParameter => {
let t1 = Date.now();
funcParameter();
let t2 = Date.now();
return t2 - t1;
};
// Write your code below
const time2p2 = timeFuncRuntime(checkThatTwoPlusTwoEqualsFourAMillionTimes);
const checkConsistentOutput(func, val) => {
let checkOne = func(val);
let checkTwo = func(val);
if (checkOne === checkTwo){
return checkOne;
} else {
return 'This function returned inconsisent results'
}
}
I'm getting the error SyntaxError: Missing initializer in const declaration. please help me understand.
I'm seeing an error in the last const declaration that appears to be because it's missing an '='.
const checkConsistentOutput(func, val) => {
...
}
const checkConsistentOutput = (func, val) => {
...
}
I need to write a function in JavaScript that takes a number and returns an object that returns chainable functions (without using OOP).
Example:
func(3).not().not().equals(4)
would outputs false.
And:
func(5).equals(5)
would output: true
This is the code I have written:
const func = (obj) => {
const obj2 = {
not: () => {
return !obj
},
equals: (num) => {
return obj === num
}
}
return obj2
}
It works when I call func(3).not() or func(5).equals(5), but doesn't allow me to chain the functions so calling func(5).not().equals(5) returns an error saying that this is not a function.
What am I not seeing here?
That's a very weird way to compose functions. Let's think about what's actually happening.
func(3).not().not().equals(4)
// is equivalent to
not(not(equals(4)(3)))
// where
const not = x => !x;
const equals = x => y => x === y;
The simplest way to implement this chain would be as follows.
const equals = x => toBool(y => x === y);
const toBool = func => ({
not: () => toBool(x => !func(x)),
func
});
const example1 = equals(4).not().not().func(3);
const example2 = equals(5).func(5);
console.log(example1); // false
console.log(example2); // true
However, this is a forward chain. You want a backward chain. Unfortunately, there's a problem.
In a forward chain .func(x) marks the end of the chain.
In a backward chain .equals(x) marks the end of the chain.
This means that in a backward chain, you wouldn't be able to write the following expression.
func(3).not().not().equals(4).add(1)
// expected to be equivalent to
not(not(equals(4)(add(1)(3))))
// but actually equivalent to
not(not(equals(4)(3))).add(1)
// which evaluates to
false.add(1)
On the other hand, you would be able to do this quite easily using a forward chain.
const id = x => x;
const toNum = func => ({
add: x => toNum(y => x + func(y)),
equals: x => toBool(y => x === func(y)),
func
});
const toBool = func => ({
not: () => toBool(x => !func(x)),
func
});
const { add, equals } = toNum(id);
const example1 = equals(4).not().not().func(3);
const example2 = add(1).equals(4).not().not().func(3);
console.log(example1); // false
console.log(example2); // true
By the way, this is an object-oriented design pattern even though it doesn't make use of classes.
My advice would be to write plain old functions.
const add = (x, y) => x + y;
const equals = (x, y) => x === y;
const not = x => !x;
const example1 = not(not(equals(4, 3)));
const example2 = not(not(equals(4, add(1, 3))));
console.log(example1); // false
console.log(example2); // true
The simplest solutions are usually the best. Source: Occam's razor.
To return another object with the same methods that wraps the new value, simply call func again:
const func = (obj) => {
const obj2 = {
not: () => {
return func(!obj)
// ^^^^^^^^^^^^^^^^^
},
equals: (num) => {
return obj === num
}
}
return obj2
}
console.log(func(3).not().not().equals(4))
console.log(func(5).equals(5))
console.log(func(3).not())
You can use a closure to store both the initial input and the state of the operation:
const func = (input) => {
let not = false
const obj = {
not: () => {
not = !not
return obj
},
equals: (num) => {
return not ? input !== num : input === num
}
}
return obj;
}
console.log(func(5).not().equals(5))
console.log(func(5).not().not().equals(5))
console.log(func(5).not().equals(4))
console.log(func(5).not().not().equals(4))
You could take an object for return as interface and store value and negation.
var object = {
func: function (value) {
object.left = value;
return object;
},
not: function() {
object.negation = !object.negation;
return object;
},
equals: function (value) {
var result = value === object.value;
return object.negation ? !result : result;
}
},
func = object.func;
console.log(func(3).not().not().equals(4));
This is a trivial question but I am having hard time to convert ternary operator to if. Here is what I tried.
function memoize(fn) {
const cache = {};
return (...args) => {
const stringifiedArgs = stringifyArgs(args);
const result = (cache[stringifiedArgs] = !cache.hasOwnProperty(
stringifiedArgs
)
? fn(...args)
: cache[stringifiedArgs]);
return result;
};
}
// function memoize(fn) {
// const cache = {};
// return (...args) => {
// const stringifiedArgs = stringifyArgs(args);
// return result = (if (cache[stringifiedArgs] = !cache.hasOwnProperty(stringifiedArgs)) {
// fn(...args);
// } else {
// cache[stringifiedArgs];
// })
// };
// }
This is the cleanest I can get it--check the property and save the result of the memoized function in the cache if it doesn't exist. Then return it from the cache.
function memoize(fn) {
const cache = {};
return (...args) => {
const stringifiedArgs = stringifyArgs(args);
if (!cache.hasOwnProperty(stringifiedArgs)) {
cache[stringifiedArgs] = fn(...args);
}
return cache[stringifiedArgs];
};
}
You could also use the in operator pretty safely here:
function memoize(fn) {
const cache = {};
return (...args) => {
const stringifiedArgs = args.join(`,`); // just for testing
if (!(stringifiedArgs in cache)) {
cache[stringifiedArgs] = fn(...args);
}
return cache[stringifiedArgs];
};
}
const fib = memoize(n => n < 2 ? n : fib(n - 1) + fib(n - 2));
console.log(fib(78));
You probably need an iife if you want to maintain the same structure. However, this is not the cleanest way to do it...
function memoize(fn) {
const cache = {};
return (...args) => {
const stringifiedArgs = stringifyArgs(args);
const result = cache[stringifiedArgs] = (() => {
if (!cache.hasOwnProperty(stringifiedArgs)) {
return fn(...args);
} else {
return cache[stringifiedArgs];
}
})();
return result;
};
}