I am having trouble printing the correct result in NodeJS, why isn't my code printing the strings in the correct way ? I feel like console.log is not called at all. Why do I get :
[Function]
[Function]
[Function]
[Function]
Expected result:
Tigrou (buddy of Spider) was here!
Spider (buddy of Tigrou) was also here!
Tigrou (buddy of Spider) are in a boat...
1 (buddy of 2)3
The code I thought would work:
function build_sentence(...args)
{
var i = 0
var s = ""
for (let arg of args)
{
if (i == 1)
{
i++
s += "(buddy of " + arg + ") "
}
else
{
s += arg + " "
i++
}
}
return s
}
function mycurry(build_sentence)
{
return function(...args)
{
if (!args)
{
return build_sentence();
}
else
{
return mycurry(build_sentence.bind(this, ...args))
}
}
}
const curried = mycurry(build_sentence);
console.log(curried("Tigrou")("Spider")(" was here!"))
console.log(curried("Spider")("Tigrou")(" was also here!"))
console.log(curried("Tigrou", "Spider", " are in a boat... "))
console.log(curried(1)(2, 3))
Here's a full working solution for you (except the string spacing)
const build_sentence_n_params = 3;
function build_sentence(...args)
{
var i = 0
var s = ""
for (let arg of args)
{
if (i == 1)
{
i++
s += "(buddy of " + arg + ") "
}
else
{
s += arg + " "
i++
}
}
return s
}
// A generic n-parameter curry helper, that returns fn return value
// after n-parameters given, and continues currying with more parameters.
// Note that in this configuration, the caller would also need
// to know how many parameters to give before a value is returned.
function ncurry(fn, n)
{
// Note that we have to return an outer function here, rather than just
// returning `curry` function directly, so `params` is unique for each
// initial call to `curried`.
return function(...args) {
// Initial arguments (note: we can use this array without copy, since
// rest params will always be a new array)
const params = args;
// This function contains the return logic without having to duplicate it below
function next() {
// If we have all params, call the given function, otherwise
// return the curry function again for more parameters
return !n || params.length >= n ? fn.call(null, ...params) : curry;
}
// The outer function is only called once, but this curry
// function will be called for each additional time.
function curry(...args) {
// Accumulate additional arguments
params.push(...args)
return next();
};
return next();
};
}
function mycurry(build_sentence)
{
// Call the generic n-parameter curry helper to generate
// a specific curry function for our purposes.
return ncurry(build_sentence, build_sentence_n_params);
}
const curried = mycurry(build_sentence);
console.log(curried("Tigrou")("Spider")(" was here!"))
console.log(curried("Spider")("Tigrou")(" was also here!"))
console.log(curried("Tigrou", "Spider", " are in a boat... "))
console.log(curried(1)(2, 3))
Your method invocations are quite confusing so I took the liberty to simplify your code.
If you run the following:
const curried = build_sentence("Tigrou", "Spider", " was here!");
console.log(curried);
You will get your desired output:
Tigrou (buddy of Spider) was here!
Why you are using the mycurry method is beyond my understanding.
When debugging your code, the sentence is already built on the first invocation, and what happens is that the subsequent invocations are not really invocations of the inner functions.
the main issue about our code is that !args is all the time false, as [] to boolean is also true.
you have to use !args.length. however you should add an extra call to your curried function usage like curried(1)(2, 3)().
the other approach is using comparison of curried function number of required params (build_sentence.length) and the number of params passed (args.length), but it's not working with spread scenario.
upd:
ex.1 - using Function.prototype.length property
const curry = fn =>
(...args) =>
fn.length <= args.length
? fn(...args)
: curry(fn.bind(this, ...args));
const func1 = (a, b, c) => `${a},${b},${c}`;
const func2 = (...args) => args.join(',');
console.log(curry(func1)(1,3)(4));
console.log(curry(func1)(1,3,4));
console.log(curry(func1)(1)(3)(4));
console.log(curry(func2)(1));
in this case currying will work fine for func1 (function that has enumerable number of arguments) because func1.length = 3. however for func2 - func2.length = 0, so (curry(func1)) will be executed after first call.
ex.2 - using number of arguments passed
const curry = fn =>
(...args) =>
!args.length
? fn()
: curry(fn.bind(this, ...args));
const func = (...args) => args.join(',');
console.log(curry(func)(1)(2,3,4)(5)());
in this case function currying will only return result of fn executing, when called with no arguments. however it will handle innumerable arguments of curried function properly.
Related
I have a reducer function like this
let reducer = (acv, cv) => {
return acv += cv;
}
function createMenus(arr){
let someValue = getNewValue();
arr.reduce(reducer, '');
//I want to bind my above someValue to reducer function so, I can append it to my string like below
}
let reducer = (acv, cv, someValue) => {
return acv += (cv+someValue);
}
I tried of doing something using bind() but not successful.
You can use closures in your code to your advantage.
You can create a function that returns a function.
createMenus below takes one argument and uses the value passed to it, returning another function that will operate in the array's reduce function, so calling reducer(someValue) actually returns another function. That function is what is passed to reduce(in the same way you are doing it above).
function getNewValue() {
return 'foo';
}
function reducer(someValue) {
return (acv, cv) => {
return acv += (cv + someValue);
}
};
function createMenus(arr){
let someValue = getNewValue();
return arr.reduce(reducer(someValue), '');
}
console.log(createMenus(['a', 'b', 'c']));
UPDATE
As #george mentioned in the coments, you could also use arrow functions to accomplish the same thing. The syntax is much shorter, but readability is in the eyes of the beholder.
let reducer = value => (a, v) => a + (v + value);
Even if you find it more readable, it is possible that you will make your code harder to debug utilizing this method as it can be harder to track down an error that occurs in an anonymous function than it is in a named function.
You can access someValue by defining reducer inside another function definition where someValue is available. (This is a use of closures in JavaScript.)
const
myArr = ["big", "medium", "tiny"],
myStr = createMenus(myArr);
console.log(myStr);
function createMenus(arr){
const
someValue = getNewValue(),
reducer = (acv, cv) => acv + (cv + someValue),
output = arr.reduce(reducer, '');
return(output);
}
function getNewValue(){
return "MenuItem, ";
}
I am new to JavaScript and have several questions about functional programming.
Here is a statement:
outer(inner(5));
Is it possible to construct function outer in a way that allows it
to capture function inner and its argument 5?
Is it possible to construct function inner in a way that allows it to
pass itself and its argument 5 to function outer?
If the answer to both questions above is no, is it possible to
construct functions outer and inner in a way that allows the former
to capture function inner and its argument 5 or the
latter to pass itself and its argument 5 to function
outer?
I tried:
using the arguments object but to no avail.
function outer (parameter) {
return arguments;
}
function inner (n) {
return n + 1;
}
console.log(outer(inner(5))); // returns Arguments { 0: 6 ... }
using currying but I do not see how it can help me since I am not given the following statement:
outer()(5);
A possible workaround consists in returning an array from inner() composed of on one side the processing function and on the other side the argument.
outer will be able to access both by reading the array.
function outer(arr)
{
var fun = arr[ 0 ];
var arg = arr[ 1 ];
var result = fun(arg);
console.log('inner function is:', fun);
console.log('its argument is:', arg);
console.log('its result is:', result);
return result;
}
function inner(num)
{
return [
function (_num)
{
return _num + 1;
},
num
]
}
console.log(outer(inner(5)));
You could achieve this by letting your inner return a function (foo) which closes over n. You can then let foo return n+1. Then, within your outer function, you can invoke foo to get its return value:
const outer = f => f();
const inner = n => _ => n+1;
console.log(outer(inner(5)));
Alternatively, another possibility would involve changing your return value. You could return an array from inner which contains the original passed through arguments (...arguments) and the returned value (to_return) and then use destructuring assignment to get the passed in argument(s) (n & m) and the returned result:
function outer([result, n, m]) {
console.log("returned from inner: ", result);
console.log("arguments passed into inner: " + [n, m]);
return n;
}
function inner(n, m) {
let to_return = n + 1;
return [to_return, ...arguments];
}
console.log(outer(inner(5, 2))); // returns 5
Note: I added an m argument to demonstrate how you can extend this to multiple arguments
function outer(myFunction, argument) {
if (typeof myFunction !== "function") {
return false;
}
return myFunction(argument);
}
function inner(n) {
return n + 1;
}
console.log(outer(inner, 5));
Just a simple approach. Don’t execute the function inner but pass it as an argument (myFunction). And let the outer function execute it with the given argument.
I know that the purpose of memoize is to cache values so code can be run faster by not having to re-calculate the same answer everytime. My issue stems from returning a function (i think). The google chrome debugger isn't that useful for me here because everytime I try to run this memoize function, it just goes from the argus variable (on line 4 i believe) all the way down to the semi-colon. Furthermore, result always returns an empty object instead of storing a value in result.
I start by defining a function:
function add(a,b){
return a+b;
}
This is my attempt at the memoize function:
_.memoize = function(func) {
var result = {};
var flag = 0;
var argus = Array.prototype.slice.call(arguments)
return function() {
if(result[key] === arguments){
flag = 1
}
else if(flag = 0){
result[argus] = func.apply(this, argus);
}
return result[argus];
};
};
I'd call memoize by doing _.memoize(add(2,5)) but the result doesn't get stored in the result object.
Am I even close to getting this memoize function working properly? Any guidance you guys can give here would be appreciated.
The biggest point you're missing is that _.memoize is called on the function first, and it returns a new function. You are calling it on the result of a function call (which is the number 7 in this case).
In order to get it to work, you need to rearrange a few things.
Also note that it's not wise to try to use an array itself as the index to an object. One approach to get around that would be to convert the arguments array to JSON and use that as the index on the results object:
function add(a, b) {
console.log('Called add(' + a + ', ' + b + ')');
return a + b;
}
var _ = {};
_.memoize = function(func) {
var results = {};
return function() {
var args = Array.prototype.slice.call(arguments);
var key = JSON.stringify(args);
if (!(key in results)) {
results[key] = func.apply(this, args);
}
return results[key];
};
};
var madd = _.memoize(add);
console.log(madd(2, 4));
console.log(madd(9, 7));
console.log(madd(2, 4));
Question: How would you make this work?
add(2)(5); // 7
add(2, 5); // 7
I am trying to solve the question above:
I know that the first solution uses currying and would be implemented as follows:
var add = functoin(x){
return function (y){
return x+y;
};
};
while the second is jsut your normal function:
var add = functoin(x,y){
return x+y;
};
Is there a way to make both work at the same time?
You can use a higher-order function to wrap other functions with that behaviour.
This kind of function is often called curry, and it comes with many libraries (lodash, for example).
curry returns a new function that checks whether all the expected arguments have been supplied. If they have, it calls originalFunction. If not, it returns a partially applied function,
This implementation uses Function#length to test call arity, so it works with any number of arguments.
function curry (fn) {
return function (...args) {
if (args.length >= fn.length) {
return fn.call(this, ...args)
} else {
return curry(fn.bind(this, ...args))
}
}
}
function add (x, y) {
return x + y;
}
// You can curry any function!
const curriedAdd = curry(add);
console.log(curriedAdd(1, 2)); // 3
console.log(curriedAdd(1)(2)); // 3
console.log(curriedAdd(1)); // a function
You could inspect the amount of arguments passed in and return one or the either depending on it:
function add(a, b) {
if (arguments.length == 2) {
return a + b;
}
return function(b) {
return add(a, b);
}
}
console.log(add(2)(5)); // 7
console.log(add(2, 5)); // 7
I'm trying to understand how a function works that is run with two parentheses and two parameters. Like so:
add(10)(10); // returns 20
I know how to write one that takes two params like so:
function add(a, b) {
return a + b;
}
add(10,10); // returns 20
How could I alter that function so it could be run with one set of parameters, or two, and produce the same result?
Any help is appreciated. Literally scratching my head over this.
Thanks in advance!
How could I alter that function so it could be run with one set of parameters, or two, and produce the same result?
You can almost do that, but I'm struggling to think of a good reason to.
Here's how: You detect how many arguments your function has received and, if it's received only one, you return a function instead of a number — and have that function add in the second number if it gets called:
function add(a,b) {
if (arguments.length === 1) {
return function(b2) { // You could call this arg `b` as well if you like,
return a + b2; // it would shadow (hide, supercede) the one above
};
}
return a + b;
}
console.log(add(10, 10)); // 20
console.log(add(10)(10)); // 20
I said "almost" above because just because the add function received only one argument, that doesn't guarantee that the caller is going to call the result. They could write:
var x = add(10);
...and never call the function that x now refers to.
Welcome to the wonderful world of first order functions
In JavaScript, a function can return a function since a function is just another object. A simple implementation is something like:
function add(x){
return function addOther(y){
return x + y;
};
}
This is possible because of closures and first order functions.
This also lets you do partial application, libraries like Ramda utilize this to great extent.
var addThree = add(3)
addThree(5); // 8
To extend what both T. J. Crowder and Benjamin Gruenbaum said, libraries like Ramda (disclosure: I'm one of the authors) allow you to convert a simple function like this:
function add(a, b) {
return a + b;
}
into the style under discussion by wrapping it in a call to a curry function:
var add = R.curry(function add(a, b) {
return a + b;
});
add(3, 5); //=> 8
add(3)(5); //=> 8
var add3 = add(3);
add3(5); //=> 8
The best article I know on this subject is Hugh Jackson's Why Curry Helps. I wrote a more detailed one at Favoring Curry.
Update
Here is a version of curry somewhat simpler than the one in Ramda. It would do the above and quite a bit more, but doesn't do some of the things that Ramda does with placeholder values:
// here is a function that takes a function and returns a curried version
// of it, that is, a version that performs the sort of partial application
// you describe.
var curry = function(fn) {
// first, we detect how many arguments the function has.
var fnArity = fn.length;
var partialApply = function(args) {
// now, let's create a function that's curried
return function () {
// collect the previous args as the partial, and add the new
// ones you just received
var newArgs = (args || []).concat([].slice.call(arguments, 0));
// if we have "enough" arguments, we don't need any more partial
// application and we can call the function.
if (newArgs.length >= fnArity) {
return fn.apply(this, newArgs);
} else { // else we return a partially applied version
return partialApply(newArgs);
}
};
};
return partialApply([]); // a function is itself partially applied with 0 args
};
function add() {
var sum = 0;
for (var i = 0; i < arguments.length; i++) {
sum += arguments[i];
}
function total() {
for (var i = 0; i < arguments.length; i++) {
sum += arguments[i];
}
return total;
}
total.toString = function () { return sum };
return total;
}
This will work for any no of arguments and parentheses.
https://medium.com/#imdebasispanda/super-function-with-closure-86a58a9a980b