Create chain in lodash with custom functions - javascript

Is there way to get my own custom function in a chain of lodash. So for example like this:
var l = [1,2,3]
var add = function(a, b){return a+b}
var r =_.chain(l).find(function(a){return a>1}).add(5).value()
=>r = 7

What you look for is a way to extend the lodash prototype. It so nicely turns out that you can do it easily with a mixin utility function. Check here the docs:
http://lodash.com/docs#mixin
In your example it will look like:
var l = [1,2,3];
var add = function(a, b){return a+b}
_.mixin({
add: add
});
var r =_.chain(l).find(function(a){return a>1}).add(5).value()
console.log(r); ==> 7
and here is live sample on fiddle: http://jsfiddle.net/g2A9C/

After #stride anwswer I came up with a more generic solution using _.mixin:
function add(a, b, c) {
return a + b + c
}
function sub(a, b, c) {
return a - b - c
}
_.mixin({
run: function (v, f) {
var args = Array.prototype.slice.call(arguments, 2)
args.unshift(v)
return f.apply(this, args)
}
})
var r = _.chain(1).run(add, 1, 1).run(sub, 2, 2).value()
console.log(r) -> -1
1 + 1 + 1 - 2 - 2 = -1
http://jsbin.com/iyEhaMa/1/
After all I wonder why this not a build in function in lodash.

Another option is to just drop chaining and leverage function composition through _.flow.
From the DOCS:
[Flow] Creates a function that returns the result of invoking the given
functions with the this binding of the created function, where each
successive invocation is supplied the return value of the previous.
This means that every function inside Flow will receive as input the output of the previous one. In practice this means we are not limited to using only Lodash API methods, but we can mix and match whatever function we fancy, as long as the next one is able to handle that return value.
var l = [1,2,3]
var add = _.curry((a, b) => a + b);
_.flow(
_.find(a => a > 1),
add(5),
)(l);
// => 7
NB - This example is using the Functional version of Lodash, if you don't want or can't use that one you can still achieve the same result, check my other answer to another question about Lodash.

Maybe it's too late but _.tap is another chance

Related

Currying function with unknown arguments in JavaScript

In a recent interview, I was asked to write a function that adds numbers and accepts parameters like this:
add(1)(2)(3) // result is 6
add(1,2)(3,4)(5) // result is 15
The number of parameters is not fixed, and the arguments can be either passed in sets or individually.
How can I implement this add function?
Given your examples, the number of parameters is fixed in some ways.
As #ASDFGerte pointed out, your examples seem to return the result after three invocations. In this case a simple implementation without introducing terms like variadic and currying could be
function add(...args1){
return function(...args2){
return function(...args3){
return args1.concat(args2).concat(args3).reduce((a,b)=>a+b)}}}
console.log(add(1)(2)(3))
console.log(add(1,2)(3,4)(5))
Every invocation accepts a variable number of parameters.
However it would be nice to generalize the construction of this nested functions structure and you can accomplish that with currying.
But if you want to allow an arbitrary number of invocations, when you should stop returning a new function and return the result? There is no way to know, and this is a simple, unaccurate and partial explanation to give you the idea of why they said you cannot accomplish what they asked you.
So the ultimate question is: is it possible that you misunderstood the question? Or maybe it was just a trick to test you
Edit
Another option would be to actually invoke the function when no arguments are passed in, change the call to add(1)(2)(3)()
Here an example recursive implementation
function sum (...args) {
let s = args.reduce((a,b)=>a+b)
return function (...x) {
return x.length == 0 ? s : sum(s, ...x)
};
}
console.log(sum(1,2)(2,3,4)(2)())
At every invocation computes the sum of current parameters and then return a new function that:
if is invoked without parameters just return the current sum
if other numbers are passed in, invokes recursively sum passing the actual sum and the new numbers
I'm a bit late to the party, but something like this would work (a bit hacky though in my opinion):
const add = (a, ...restA) => {
const fn = (b, ...restB) => {
return add([a, ...restA].reduce((x, y) => x + y) + [b, ...restB].reduce((x, y) => x + y))
};
fn.valueOf = () => {
return [a, ...restA].reduce((x, y) => x + y)
};
return fn;
}
This function returns a function with a value of the sum. The tests below are outputing the coerced values instead of the actual functions.
console.log(+add(1,2)(3,4)(5)); // 15
console.log(+add(1)) // 1
console.log(+add(1)(2)) // 3
console.log(+add(1)(2)(3)) // 6
console.log(+add(1)(2)(3)(4)) // 10
Since it's a currying function, it will always return another function so you can do something like this:
const addTwo = add(2);
console.log(+addTwo(5)); // 7
using reduce and spread it can be done as below
function calc(...args1){
return function (...args2){
return function (...args3){
let merge = [...args1, ...args2, ...args3]
return merge.reduce((x ,y)=> x + y) ;
}
}
}
let sum = calc(10)(1)(4);
console.log("sum",sum);
They probably wanted to know how comfortable you were with "javascript internals", such as how and when methods like Function#toString and Function#valueOf, Function#[Symbol.toPrimitive] are called under the hood.
const add = (...numbers) => {
const cadd = (...args) => add(...args, ...numbers);
cadd[Symbol.toPrimitive] = () => numbers.reduce((a, b) => a + b);
return cadd;
}
console.log(
`add(1,2)(3,4)(5) =>`, add(1,2)(3,4)(5),
); // result is 15
console.log(
`add(1,2) =>`, add(1,2),
); // result is 3
console.log(
`add(1,2)(5)(1,2)(5)(1,2)(5)(1,2)(5) =>`, add(1,2)(5)(1,2)(5)(1,2)(5)(1,2)(5),
); // result is 32

How is this operation called in JavaScript [duplicate]

As can be seen in the Mozilla changlog for JavaScript 1.7 they have added destructuring assignment. Sadly I'm not very fond of the syntax (why write a and b twice?):
var a, b;
[a, b] = f();
Something like this would have been a lot better:
var [a, b] = f();
That would still be backwards compatible. Python-like destructuring would not be backwards compatible.
Anyway the best solution for JavaScript 1.5 that I have been able to come up with is:
function assign(array, map) {
var o = Object();
var i = 0;
$.each(map, function(e, _) {
o[e] = array[i++];
});
return o;
}
Which works like:
var array = [1,2];
var _ = assign[array, { var1: null, var2: null });
_.var1; // prints 1
_.var2; // prints 2
But this really sucks because _ has no meaning. It's just an empty shell to store the names. But sadly it's needed because JavaScript doesn't have pointers. On the plus side you can assign default values in the case the values are not matched. Also note that this solution doesn't try to slice the array. So you can't do something like {first: 0, rest: 0}. But that could easily be done, if one wanted that behavior.
What is a better solution?
First off, var [a, b] = f() works just fine in JavaScript 1.7 - try it!
Second, you can smooth out the usage syntax slightly using with():
var array = [1,2];
with (assign(array, { var1: null, var2: null }))
{
var1; // == 1
var2; // == 2
}
Of course, this won't allow you to modify the values of existing variables, so IMHO it's a whole lot less useful than the JavaScript 1.7 feature. In code I'm writing now, I just return objects directly and reference their members - I'll wait for the 1.7 features to become more widely available.
You don't need the dummy "_" variable. You can directly create "global" variables by using the window object scope:
window["foo"] = "bar";
alert(foo); // Gives "bar"
Here are few more points:
I wouldn't name this function
"assign" because that's too generic
a term.
To more closely resemble JS
1.7 syntax, I'd make the function take the destination as the first
argument and the source as the
second argument.
Using an object literal to pass the destination variables is cool but can be confused with JS 1.7 destructuring where the destination is actually an object and not an array. I prefer just using a comma delimited list of variable names as a string.
Here's what I came up with:
function destructure(dest, src) {
dest = dest.split(",");
for (var i = 0; i < src.length; i++) {
window[dest[i]] = src[i];
}
}
var arr = [42, 66];
destructure("var1,var2", arr);
alert(var1); // Gives 42
alert(var2); // Gives 66
Here's what I did in PHPstorm 10:
File -> Settings -> Languages & Frameworks -> ...
... set JavaScript language version to e.g. JavaScript 1.8.5...
-> click Apply.
In standard JavaScript we get used to all kinds of ugliness, and emulating destructuring assignment using an intermediate variable is not too bad:
function divMod1(a, b) {
return [ Math.floor(a / b), a % b ];
}
var _ = divMod1(11, 3);
var div = _[0];
var mod = _[1];
alert("(1) div=" + div + ", mod=" + mod );
However I think the following pattern is more idomatic:
function divMod2(a, b, callback) {
callback(Math.floor(a / b), a % b);
}
divMod2(11, 3, function(div, mod) {
alert("(2) div=" + div + ", mod=" + mod );
});
Note, that instead of returning the two results as an array, we pass them as arguments to a callback function.
(See code running at http://jsfiddle.net/vVQE3/ )

Simple JavaScript Function that returns the parameter of greater value

I'm learning how to build functions and my task is to create a function declaration that will return the parameter of greater value. So far, I've only learned how to sums and products -- in other words, I don't know how to get JavaScript to "decide" which parameter is greater.
The extact task description is as follows: Build a function declaration called maxOf2 that takes in two numbers and returns the greater value. Be careful to think about the possibility of equality as well and return one of the numbers.
I've read about Math.max(), but as the course hasn't covered that, I'm not supposed to use it.
Here is what I have so far, which is not much:
function maxOf2(a, b) {
var a = 12;
var b = 4;
return ...;
}
Very basic example:
function maxOf(a, b){
if(a > b){
return a;
} else {
return b;
}
}
You can use that Math.max() function like so:
Math.max(a, b);
And another example that uses ternary operator:
function maxOf(a, b){
return a > b ? a : b;
}
Another answer because there are only 3 answers:
const maxOf = (a,b) => (a > b ? a : b);

JavaScript can return argument?

I have two functions:
function g(data, i){}
function f(data, i){}
I want to call them like:
var myVar = f(g(data, i));
So g() should return (data, i).
Of course, it doesn't work. Is there some way to do this?
Returning multiple values is not supported by Javascript (at least not in the implementations that most browsers have).
Do the following:
function g(data, i) {
// some code
return {
data: data,
i: i
};
}
var o = g(data, i);
f(o.data, o.i);
Note:
As mentioned by Phil in the Question's comments, if i is not modified in g(), then you can just call f(g(data, i), i) without modifying function g.
there is, if you use apply and make your functions return arrays of values.
function g(a, b) { return [a, b]; }
function f(c, d) { return [c, d]; }
console.log(f.apply(null, g("thing", "cow")));
This is, however, a great sign of a bad programmer if used for this purpose, so you don't want to do this. If you have functions that take two arguments, pass two arguments:
function g(a, b) { return [a, b]; }
function f(c, d) { return [c, d]; }
var result = g("thing", "cow");
f(result[0], result[1]);
because you already know it takes, and generates, a pair of values, or use the object pattern (rather than an array) that Der Flatulator shows you.
Not exactly like you have it, however you can trick it since arguments is "array-like" ... behold :D
var g = function(a,b) {return [a,b]};
var f = function(a, b) {console.log("f evaluating", a, b)};
f.apply(null,g(1,2));
gives you:
bar 1 2
Alternatively you could do something hacky in your (f) function to split the values of the first argument if there is only one argument passed in, but I like the apply better, especially cuz this is horrible if for example your a argument is an array by itself.
Works for any number of argument length
function g(){
return [].slice.call(arguments);
}
function f(data, i){
}
f.apply(undefined, g(data, i));

Destructuring assignment in JavaScript

As can be seen in the Mozilla changlog for JavaScript 1.7 they have added destructuring assignment. Sadly I'm not very fond of the syntax (why write a and b twice?):
var a, b;
[a, b] = f();
Something like this would have been a lot better:
var [a, b] = f();
That would still be backwards compatible. Python-like destructuring would not be backwards compatible.
Anyway the best solution for JavaScript 1.5 that I have been able to come up with is:
function assign(array, map) {
var o = Object();
var i = 0;
$.each(map, function(e, _) {
o[e] = array[i++];
});
return o;
}
Which works like:
var array = [1,2];
var _ = assign[array, { var1: null, var2: null });
_.var1; // prints 1
_.var2; // prints 2
But this really sucks because _ has no meaning. It's just an empty shell to store the names. But sadly it's needed because JavaScript doesn't have pointers. On the plus side you can assign default values in the case the values are not matched. Also note that this solution doesn't try to slice the array. So you can't do something like {first: 0, rest: 0}. But that could easily be done, if one wanted that behavior.
What is a better solution?
First off, var [a, b] = f() works just fine in JavaScript 1.7 - try it!
Second, you can smooth out the usage syntax slightly using with():
var array = [1,2];
with (assign(array, { var1: null, var2: null }))
{
var1; // == 1
var2; // == 2
}
Of course, this won't allow you to modify the values of existing variables, so IMHO it's a whole lot less useful than the JavaScript 1.7 feature. In code I'm writing now, I just return objects directly and reference their members - I'll wait for the 1.7 features to become more widely available.
You don't need the dummy "_" variable. You can directly create "global" variables by using the window object scope:
window["foo"] = "bar";
alert(foo); // Gives "bar"
Here are few more points:
I wouldn't name this function
"assign" because that's too generic
a term.
To more closely resemble JS
1.7 syntax, I'd make the function take the destination as the first
argument and the source as the
second argument.
Using an object literal to pass the destination variables is cool but can be confused with JS 1.7 destructuring where the destination is actually an object and not an array. I prefer just using a comma delimited list of variable names as a string.
Here's what I came up with:
function destructure(dest, src) {
dest = dest.split(",");
for (var i = 0; i < src.length; i++) {
window[dest[i]] = src[i];
}
}
var arr = [42, 66];
destructure("var1,var2", arr);
alert(var1); // Gives 42
alert(var2); // Gives 66
Here's what I did in PHPstorm 10:
File -> Settings -> Languages & Frameworks -> ...
... set JavaScript language version to e.g. JavaScript 1.8.5...
-> click Apply.
In standard JavaScript we get used to all kinds of ugliness, and emulating destructuring assignment using an intermediate variable is not too bad:
function divMod1(a, b) {
return [ Math.floor(a / b), a % b ];
}
var _ = divMod1(11, 3);
var div = _[0];
var mod = _[1];
alert("(1) div=" + div + ", mod=" + mod );
However I think the following pattern is more idomatic:
function divMod2(a, b, callback) {
callback(Math.floor(a / b), a % b);
}
divMod2(11, 3, function(div, mod) {
alert("(2) div=" + div + ", mod=" + mod );
});
Note, that instead of returning the two results as an array, we pass them as arguments to a callback function.
(See code running at http://jsfiddle.net/vVQE3/ )

Categories

Resources