Having two functions one wrapping the other, how to pass a parameter down correctly? At the moment the console logging does not work.
const a = (v) => (v) => console.log(v);
a(2);
Passing a parameter in High order fn is easy as the value get set to closure
const a = v => () => {console.log(v)};
a(2)()
No matter how deep you go, parameter passed to fn get set to closure space when a fn having a parameter v either returns a fn or executes a fn which uses that parameter v
const a = v => () => () => () => {console.log(v)}
a(2)()()()
If you really want to work on two functions
const a = (v) => (a = v) => console.log(a);
a(2)()
What you did over there to define a lambda function within a function.
If you want it to work with a(2) you need to excecture the inner function (meaning to add () at the end), like this:
const a = (v) => (() => console.log(v))();
a(2);
This (() => console.log(v)) is a function, when you add () at the end it's actually activating that function, and that's why what you did, didn't work.
You have two v variables, and the inner one is shadowing the outer one since they have the same name. Unless you rename the inner v, there's no way to access the outer v from inside that function.
Related
Let's say I have a function that takes a function as an argument and returns another function that takes a value that it passes to the function passed as an argument:
const curry = f => x => f(x);
Is it possible to type this function using Flow Type in such a way that the return value of curry is determined by the function f passed in if that function has been typed?
I tried this:
const numToStr = (x: number): string => x.toString();
const curry = <F: Function>(f: F): (mixed => *) => (x: mixed): * => f(x);
const curried = curry(numToStr);
link
The result of passing the first argument is that the resulting function curried has a signature like this:
(((x: mixed) => any) | ((x: mixed) => empty))
This makes sense, either the result is empty or it's anything. What I'd hoped is that because numToStr is typed, that it'd be possible for Flow to understand that curried is really number => string.
Is there a way to do this that I've missed? If not, can anyone explain why.
Currying usually applies to the process of taking a function of two arguments and transforming it into a function of one argument that returns another function of one argument which returns the result.
In Flow it would look like this:
const curry = <A, B, C>(f: (A, B) => C): (A => (B => C)) => (x) => (y) => f(x, y);
const prefixNum = (prefix: string, x: number): string => prefix + x.toString();
const prefixed = curry(prefixNum);
const withHello = prefixed("hello ");
const result = withHello(3); // "hello 3"
Your version is a bit different. You are transforming a function of one argument into a function of zero arguments. This is more like lazy evaluation than currying: supply all of the arguments but only return a zero-argument function (sometimes called a "thunk"), which actually performs the computation when you call it. The implementation could look like this:
const makeLazy = <A, C>(f: A => C): (A => (() => C)) => (x) => () => f(x);
It's essentially the definition above, but with one of the types replaced with (). This should work how you want it to:
const numToStr = (x: number): string => x.toString();
const lazyNumToStr = makeLazy(numToStr);
const thunk = lazyNumToStr(3);
thunk(); // "3"
I am following a tutorial on firebase authentication in ReactJS. In the code, I stumbled across such function:
const byPropKey = (propertyName, value) => () => ({
[propertyName]: value,
});
I suppose this function is used to set state of a React component. It is used like so:
<input
value={username}
onChange={event => this.setState(byPropKey('username', event.target.value))}
type="text"
placeholder="Full Name"
/>
I am a newcomer to React, JavaScript, ES6 and functional programming in general, so this confuses the hell out of me. I know that the double arrow notation indicates a curried function, which enables partial application of the function. In this case, however, I can not see how this gets used in such scenario.
Here is the tutorial I am referring to:
tutorial
I can not see how this gets used in such scenario.
The tutorial author is currying that function because setState can take either an object or a function. A function gives you access to the previous state and props. Here is a sandbox example.
In the example you provided, the tutorial author is not using the partial application, and thus not leveraging the access to previous state and props. So in this specific case, a non curried implementation (passing an object to setState) would do just fine.
However, if you were to add to this tutorial codebase, the future code might require byPropKey to access the prevState and props:
const byPropKey = (propertyName, value) => (prevState, props) => {
//... do something with prevState and props
return {
[propertyName]: value,
}
};
... which is probably why the tutorial author wrote the function curried.
byPropKey
function uses as helper to map state and returns result like:
{ "statePiceName": value }
to set your state.
Same behavior without this function:
{event => this.setState({ username: event.target.value })}
Also you can just console.log(byPropKey('key', 'customValue')) and see how its works.
You misunderstand the double arrow. This just creates a function, not necessarily a curried or partial function.
For example:
// just a function
let doSomething = () => console.log("did something")
//call it
doSomething()
You can return another function from a function (aka a higher-order function), which is what's going on in your example:
// this will return the function () => console.log("said " + something)
let saySomething = (something) => () => console.log("said " + something)
// call the above function, which returns a different function
let sayHello = saySomething("Hello")
// now call that function
sayHello()
You can make partial functions with bind:
function add(a, b) {console.log(a + b)}
let addFive = add.bind(null, 5)
addFive(3)
addFive(10)
To take it one more step, you can make a generic function to add whatever:
// just a regular function
let add = (a,b) => console.log(a + b)
// a function to create a partial of the above based on passed in argument
let addThis = (a) => add.bind(null, a)
// make an add-10 function
let addTen = addThis(10)
// call it
addTen(12)
// make an add-33 function
let add33 = addThis(33)
add33(100)
EDIT: In response to the comments
Curried functions are those the break down larger functions that take multiple arguments into smaller functions that take fewer or one argument.
For example this simple function:
let add = (a, b, c) => a + b + c
can be curried into three functions that each take a single argument like this:
let addCurried = (a) => (b) => (c) => a + b + c
You can call this with some or all the arguments to get the result or a partial:
// non curried: F(a, b, c) -> sum
// curried: F():a -> (b -> (c -> sum))
let addCurried = (a) => (b) => (c) => a + b + c
// add everything
let total = addCurried(1)(2)(3) // -> 6
// make a partial
let addTwoAndThree = addCurried(2)(3)
// call it
let total2 = addTwoAndThree(100) //-> 105
console.log(total, total2)
It's hard to see given the definition of currying how a function that accepts two arguments and returns function the accepts none is considered currying that function.
I have an array of functions. Then I use forEach loop to pass the argument to these functions. Although when I try to call first function I get undefined in the console instead of 'hey'
Then I try to make a new array from the old one. And try to use map to get the array of functions with the argument passed into each one, but I get an array of three undefined items instead, so I can't even call a function.
const arr = [(arg) => {console.log(arg)}, (arg) => {}, (arg) => {} ];
arr.forEach(func => func('hey'));
arr[0]();
const arr2 = arr.map(func => func('ho'));
console.log(arr2);
arr2[0]();
What's the matter in both cases?
There's no problem in the first case, though arr[0](); will just print undefined because you've passed no argument.
In the second case, the resulting array contains the result of the invocation of each function, each of which returns undefined, so there are no functions in arr2 to invoke.
Your code snippet had the JS in the HTML section, so it didn't run at all.
const arr = [(arg) => { console.log(arg) }, (arg) => {}, (arg) => {}];
arr.forEach(func => func('hey'));
arr[0](); // <-- You're passing no argument here
// This invokes the functions, and builds an array of the functions'
// return values, all of which are `undefined`.
const arr2 = arr.map(func => func('ho'));
console.log(arr2);
arr2[0]();
See the following code snippet:
const
fun1 = () => Either.of(1),
fun2 = () => Either.of(2),
fun3 = () => Either.of(3),
fun4 = curry((x, y, z) => Either.of(x + y + z)),
fun5 = x => Either.of(x + 1),
fun6 = () => pipeK(
() => sequence(Either.of, [fun1(), fun2(), fun3()]),
apply(fun4),
fun5
)(),
result = fun6() // returns 7
fun4 requires 3 arguments and I'd like to give them only if all of them are right arguments. That is, sequence will apply each monadic value so I'll get them as a single right containg the raw fun1, fun2, fun3 return values.
Is this the recommended approach?
Click here for run the whole code snippet
No, I would not use sequence with an array and apply. I think the more idiomatic approach is to use ap:
const fun6 = () => chain(fun5, unnest(ap(ap(ap(Either.of(fun4), fun1()), fun2()), fun3())));
// or
const fun6 = () => chain(fun5, unnest(ap(ap(map(fun4, fun1()), fun2()), fun3())));
// or
const fun6 = () => Either.of(fun4).ap(fun1()).ap(fun2()).ap(fun3()).chain(identity).chain(fun5);
The equivalent in Haskell would be fun5 =<< join (fun4 <$> fun1 <*> fun2 <*> fun3). The unnest is needed when fun4 returns an Either, which might not be necessary.
How can I convert this function composition into more readable format?
funcA(argumentA, funcB(argumentA, funcC(argumentA, argumentB)))
What I'd like to achieve is something more like this:
compose(funcC, funcB, funcA)(argumentA, argumentB)
I'm using this compose function implementation:
const compose = (...fns) => fns.reduce((f, g) => (...args) => f(g(...args)))
The problem is I need argumentA in all function calls as a first parameter and every function returns a value to be passed as a second parameter to the next function. I know I could create separate function-returning functions and use them like so:
compose(funcCWithArg(argumentA), funcBWithArg(argumentA), funcAWithArg(argumentA))(argumentB)
but in my actual case there aren't only three of them, but many more and that would require some serious amount of code just to write them down. Is there a simpler way to do that?
EDIT: I can't use any external library. Only vanilla js.
Using vanilla JS,
const compose = (...fns) => (arg1, arg2) => fns.reduce((arg, f) => f(arg1, arg), arg2);
Explanation
compose becomes a function returning a function, which loops through the list of functions passed to it, passing the first argument to every function call.
Test
const sum = (a, b) => (a + b);
const mult = (a, b) => (a * b);
compose(sum, mult)(2, 3) === mult(2, sum(2, 3)); // true
It's not hard to write a function like this:
const link = (...fns) => (a, ...args) =>
fns.slice(1).reduce((val, fn) => fn(a, val), fns[0](a, ...args));
If you wanted it to be robust enough to handle errors gracefully, it would take more. But this should be a start.
You would use it like this:
const funcA = (x, y) => `funcA(${x}, ${y})`;
const funcB = (x, y) => `funcB(${x}, ${y})`;
const funcC = (x, y) => `funcC(${x}, ${y})`;
link(funcA, funcB, funcC)('argumentA', 'argumentB');
//=> "funcC(argumentA, funcB(argumentA, funcA(argumentA, argumentB)))"
You can see this in action on Runkit.
(And obviously you can do a reverse if you want the opposite argument order.)
First create new functions that are partial applications using bind. Then use the compose function you already have:
const funcA = (x, y) => `A(${x}, ${y})`;
const funcB = (x, y) => `B(${x}, ${y})`;
const funcC = (x, y) => `C(${x}, ${y})`;
const compose = (...fns) => fns.reduce((f, g) => (...args) => f(g(...args)));
const partials = (...fns) => (...args) => fns.map((f) => f.bind(this, ...args));
console.log(compose(...partials(funcA, funcB, funcC)("a"))("b"));
// Output:
// A(a, B(a, C(a, b)))
UPDATE
You can also build a single function that composes the partials with the first argument passed and then calls them with the other arguments. (I think this is what you want? I wasn't 100% sure what to do with more than two arguments.)
const partialCompose = (...fns) => (...args) => compose(...partials(...fns)(args[0]))(...args.slice(1));
console.log(partialCompose(funcA, funcB, funcC)("a", "b")); // same output as above