Ramda apply an argument to both functions and compose them point free - javascript

I have two curried functions f and g:
f: a -> b -> c
g: a -> c -> d
I want to create h:
h: a -> b -> d
Currently I'm composing them via pipe:
const h = a => pipe(f(a), g(a));
Is there a way to do this point free?
The reason why I ask is because I want to make the code as readable as possible. In some of my cases there are more that two functions that receive initial arguments in the composition and I'm trying to avoid repeatedly passing arguments.
I tried something like:
const h = converge(pipe, [f, g]);
which for some reason doesn't work. I guess I don't understand converge correctly.
Edit:
I tried what you suggested Ori Drori, but it doesn't work.
const modulo = divisor => dividend => dividend % divisor;
const maybeReduceByModulo = modulo => number =>
number >= 0 ? number : number + modulo;
export const maybeReducedModulo = flip(ap)(modulo, maybeReduceByModulo);
/**
* Before:
* export const maybeReducedModulo = divisor =>
* pipe(modulo(divisor), maybeReduceByModulo(divisor));
*/

Ramda (disclaimer: I'm a Ramda author) cannot directly offer every combinator one might need. It does contain a number of them. But for those it doesn't contain, it's often trivial to write your own version. For me the big problem is in naming. It's hard to come up with names for them, and even those who resort to bird names can only give names for a few of the infinity of possibilities.
I can't find this one in Avaq's handy list of combinators, nor can I find :: (a -> b -> c) -> (a -> c -> d) -> a -> b -> d or :: (a -> b -> c) -> (a -> c -> d) -> (a -> b -> d) on Hoogle, which makes me suspect that this is a fairly uncommon requirement. But if it's a requirement you have, invent your own name.
Once you've chosen a name, such combinators often write themselves.
const foo = (f) => (g) => (x) => (y) => g (x) (f (x) (y))
const f = (a) => (b) => `f (${a}, ${b})`
const g = (a) => (c) => `g (${a}, ${c})`
const h = foo (f) (g)
console .log (h ('a') ('b'))
And of course you can play with the signatures in various ways. Ramda's curry might help here. Perhaps we want this:
const foo = (f, g) => (x) => (y) => g (x) (f (x) (y))
const h = foo (f, g)
or even further, this:
const foo = curry ((f, g) => curry ((x, y) => g (x) (f (x) (y))))
const h = foo (f, g) // equivalent: `foo (f) (g)`
h ('a', 'b') // equivalent: `h ('a') ('b')`
The suggestion from customcommander does work:
const f = (a) => (b) => `f (${a}, ${b})`
const g = (a) => (c) => `g (${a}, ${c})`
const h = compose (apply (pipe), ap ([f, g]), of)
console .log (h ('a') ('b'))
<script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.27.1/ramda.min.js"></script>
<script> const {compose, apply, pipe, ap, of} = R </script>
But I think it's not nearly as understandable as the more explicit vanilla JS version.

Related

Implementing the delimited continuation monad in JavaScript - `reset` idempotence bug

This is a tough one. I've been trying to code up various monads and this was the only one I couldn't find a succinct example anywhere, so I tried writing my own shift and reset using this test suite (JS) and this question (Agda) as reference. In particular,
shift : ∀ {r o i j a} → ((a → DCont i i o) → DCont r j j) → DCont r o a
shift f = λ k → f (λ x → λ k′ → k′ (k x)) id
reset : ∀ {r i a} → DCont a i i → DCont r r a
reset a = λ k → k (a id)
The problem I have is that my implementation fails when I test for aborting through multiple resets:
// Delimited continuation monad
class DCont {
static of (x) { return new DCont(resolve => resolve(x)) }
constructor (run) { this.run = run }
chain (fn) { return new DCont(resolve => this.run(x => fn(x).run(resolve))) }
map (fn) { return this.chain(x => DCont.of(fn(x))) }
ap (dc) { return this.chain(fn => dc.map(fn)) }
shift (subc) { return new DCont(resolve => subc(dc => dc.map(resolve)).run(x => x)) }
static reset (comp) { return DCont.of(comp(DCont.of(x => x)).run(x => x)) }
}
// Setup tests
let sqr = x => x * x,
single_shift_reset = DCont
.reset(p => p
.shift(k => k(k(DCont.of(5))))
.map(x => x + 1))
.map(x => x * 2),
multi_shift_abort = DCont
.reset(p => DCont
.reset(p2 => p
.shift(k => DCont.of(5))
.map(x => 1000))
.map(x => x + 1))
.map(x => x * 2),
liftM2 = (f, m1, m2) => m1.chain(x => m2.map(y => f(x, y))),
listOf = (m1, m2) => liftM2((x, y) => [x, y], m1, m2),
add = (x, y) => x + y,
multi_shift_in_reset = DCont
.reset(p => liftM2(add,
p.shift(k => listOf( k(DCont.of(1)), k(DCont.of(2)) )),
p.shift(k => listOf( k(DCont.of(10)), k(DCont.of(20)) ))
));
// Run tests
console.log(single_shift_reset.run(sqr)) // Expects 196 = ((5 + 1 + 1) * 2) ^ 2
console.log(multi_shift_abort.run(sqr)) // Expects 100 = (5 * 2) ^ 2
console.log(multi_shift_in_reset.run(x => x)) // Expects [[11, 21], [12, 22]]
My version feels wrong - there is only one id in the reference, mine has two. Past that I'm stumped though. Any hints in the right direction would be appreciated!
Here's the problem.
The Adga implementation of delimited continuations doesn't take regions into account.
The JavaScript implementation of delimited continuations does take regions into account.
You're trying to use the Adga implementation of delimited continuations along with the JavaScript test suite, and hence you're not getting very far.
Delimited Continuations without Regions
Consider the following program.
example = do
x <- reset $ do
x <- reset $ do
shift (\k -> return 5)
return 1000
return (x + 1)
return (x * 2)
result = run example (\x -> x ^ 2)
When using delimited continuations without regions, each shift is delimited to the closest reset. Hence, in the above program the result is ((5 + 1) * 2) ^ 2 which evaluates to 144.
Your implementation of shift and reset is based on the Agda implementation. Hence, it evaluates to 144. There's also a Haskell implementation of delimited continuations without regions which is simpler.
Delimited Continuations with Regions
Now, consider the same program using delimited continuations with regions.
example = do
x <- reset $ \p -> do
x <- reset $ \p' -> do
shift p (\k -> return 5)
return 1000
return (x + 1)
return (x * 2)
result = run example (\x -> x ^ 2)
Here, we explicitly specify that the shift is delimited by the outer reset. Hence, the result is (5 * 2) ^ 2 which evaluates to 100.
The implementation of delimited continuations with regions is more complex. A good place to start would be to read the original paper by my professor, Amr Sabry, et al., A Monadic Framework for Delimited Continuations.

How to reconcile Javascript with currying and function composition

I love currying but there are a couple of reasons why a lof of Javascript devs reject this technique:
aesthetic concerns about the typical curry pattern: f(x) (y) (z)
concerns about performance penalties due to the increased number of function calls
concerns about debugging issues because of the many nested anonymous functions
concerns about readability of point-free style (currying in connection with composition)
Is there an approach that can mitigate these concerns so that my coworkers don't hate me?
Note: #ftor answered his/her own question. This is a direct companion to that answer.
You're already a genius
I think you might've re-imagined the partial function – at least, in part!
const partial = (f, ...xs) => (...ys) => f(...xs, ...ys);
and it's counter-part, partialRight
const partialRight = (f, ...xs) => (...ys) => f(...ys, ...xs);
partial takes a function, some args (xs), and always returns a function that takes some more args (ys), then applies f to (...xs, ...ys)
Initial remarks
The context of this question is set in how currying and composition can play nice with a large user base of coders. My remarks will be in the same context
just because a function may return a function does not mean that it is curried – tacking on a _ to signify that a function is waiting for more args is confusing. Recall that currying (or partial function application) abstracts arity, so we never know when a function call will result in the value of a computation or another function waiting to be called.
curry should not flip arguments; that is going to cause some serious wtf moments for your fellow coder
if we're going to create a wrapper for reduce, the reduceRight wrapper should be consistent – eg, your foldl uses f(acc, x, i) but your foldr uses f(x, acc, i) – this will cause a lot of pain amongst coworkers that aren't familiar with these choices
For the next section, I'm going to replace your composable with partial, remove _-suffixes, and fix the foldr wrapper
Composable functions
const partial = (f, ...xs) => (...ys) => f(...xs, ...ys);
const partialRight = (f, ...xs) => (...ys) => f(...ys, ...xs);
const comp = (f, g) => x => f(g(x));
const foldl = (f, acc, xs) => xs.reduce(f, acc);
const drop = (xs, n) => xs.slice(n);
const add = (x, y) => x + y;
const sum = partial(foldl, add, 0);
const dropAndSum = comp(sum, partialRight(drop, 1));
console.log(
dropAndSum([1,2,3,4]) // 9
);
Programmatic solution
const partial = (f, ...xs) => (...ys) => f(...xs, ...ys);
// restore consistent interface
const foldr = (f, acc, xs) => xs.reduceRight(f, acc);
const comp = (f,g) => x => f(g(x));
// added this for later
const flip = f => (x,y) => f(y,x);
const I = x => x;
const inc = x => x + 1;
const compn = partial(foldr, flip(comp), I);
const inc3 = compn([inc, inc, inc]);
console.log(
inc3(0) // 3
);
A more serious task
const partial = (f, ...xs) => (...ys) => f(...xs, ...ys);
const filter = (f, xs) => xs.filter(f);
const comp2 = (f, g, x, y) => f(g(x, y));
const len = xs => xs.length;
const odd = x => x % 2 === 1;
const countWhere = f => partial(comp2, len, filter, f);
const countWhereOdd = countWhere(odd);
console.log(
countWhereOdd([1,2,3,4,5]) // 3
);
Partial power !
partial can actually be applied as many times as needed
const partial = (f, ...xs) => (...ys) => f(...xs, ...ys)
const p = (a,b,c,d,e,f) => a + b + c + d + e + f
let f = partial(p,1,2)
let g = partial(f,3,4)
let h = partial(g,5,6)
console.log(p(1,2,3,4,5,6)) // 21
console.log(f(3,4,5,6)) // 21
console.log(g(5,6)) // 21
console.log(h()) // 21
This makes it an indispensable tool for working with variadic functions, too
const partial = (f, ...xs) => (...ys) => f(...xs, ...ys)
const add = (x,y) => x + y
const p = (...xs) => xs.reduce(add, 0)
let f = partial(p,1,1,1,1)
let g = partial(f,2,2,2,2)
let h = partial(g,3,3,3,3)
console.log(h(4,4,4,4))
// 1 + 1 + 1 + 1 +
// 2 + 2 + 2 + 2 +
// 3 + 3 + 3 + 3 +
// 4 + 4 + 4 + 4 => 40
Lastly, a demonstration of partialRight
const partial = (f, ...xs) => (...ys) => f(...xs, ...ys);
const partialRight = (f, ...xs) => (...ys) => f(...ys, ...xs);
const p = (...xs) => console.log(...xs)
const f = partialRight(p, 7, 8, 9);
const g = partial(f, 1, 2, 3);
const h = partial(g, 4, 5, 6);
p(1, 2, 3, 4, 5, 6, 7, 8, 9) // 1 2 3 4 5 6 7 8 9
f(1, 2, 3, 4, 5, 6) // 1 2 3 4 5 6 7 8 9
g(4, 5, 6) // 1 2 3 4 5 6 7 8 9
h() // 1 2 3 4 5 6 7 8 9
Summary
OK, so partial is pretty much a drop in replacement for composable but also tackles some additional corner cases. Let's see how this bangs up against your initial list
aesthetic concerns: avoids f (x) (y) (z)
performance: unsure, but i suspect performance is about the same
debugging: still an issue because partial creates new functions
readability: i think readability here is pretty good, actually. partial is flexible enough to remove points in many cases
I agree with you that there's no replacement for fully curried functions. I personally found it easy to adopt the new style once I stopped being judgmental about the "ugliness" of the syntax – it's just different and people don't like different.
The current prevailing approach provides that each multi argument function is wrapped in a dynamic curry function. While this helps with concern #1, it leaves the remaining ones untouched. Here is an alternative approach.
Composable functions
A composable function is curried only in its last argument. To distinguish them from normal multi argument functions, I name them with a trailing underscore (naming is hard).
const comp_ = (f, g) => x => f(g(x)); // composable function
const foldl_ = (f, acc) => xs => xs.reduce((acc, x, i) => f(acc, x, i), acc);
const curry = f => y => x => f(x, y); // fully curried function
const drop = (xs, n) => xs.slice(n); // normal, multi argument function
const add = (x, y) => x + y;
const sum = foldl_(add, 0);
const dropAndSum = comp_(sum, curry(drop) (1));
console.log(
dropAndSum([1,2,3,4]) // 9
);
With the exception of drop, dropAndSum consists exclusively of multi argument or composable functions and yet we've achieved the same expressiveness as with fully curried functions - at least with this example.
You can see that each composable function expects either uncurried or other composable functions as arguments. This will increase speed especially for iterative function applications. However, this is also restrictive as soon as the result of a composable function is a function again. Look into the countWhere example below for more information.
Programmatic solution
Instead of defining composable functions manually we can easily implement a programmatic solution:
// generic functions
const composable = f => (...args) => x => f(...args, x);
const foldr = (f, acc, xs) =>
xs.reduceRight((acc, x, i) => f(x, acc, i), acc);
const comp_ = (f, g) => x => f(g(x));
const I = x => x;
const inc = x => x + 1;
// derived functions
const foldr_ = composable(foldr);
const compn_ = foldr_(comp_, I);
const inc3 = compn_([inc, inc, inc]);
// and run...
console.log(
inc3(0) // 3
);
Operator functions vs. higher order functions
Maybe you noticed that curry (form the first example) swaps arguments, while composable does not. curry is meant to be applied to operator functions like drop or sub only, which have a different argument order in curried and uncurried form respectively. An operator function is any function that expects only non-functional arguments. In this sence...
const I = x => x;
const eq = (x, y) => x === y; // are operator functions
// whereas
const A = (f, x) => f(x);
const U = f => f(f); // are not operator but a higher order functions
Higher order functions (HOFs) don't need swapped arguments but you will regularly encounter them with arities higher than two, hence the composbale function is useful.
HOFs are one of the most awesome tools in functional programming. They abstract from function application. This is the reason why we use them all the time.
A more serious task
We can solve more complex tasks as well:
// generic functions
const composable = f => (...args) => x => f(...args, x);
const filter = (f, xs) => xs.filter(f);
const comp2 = (f, g, x, y) => f(g(x, y));
const len = xs => xs.length;
const odd = x => x % 2 === 1;
// compositions
const countWhere_ = f => composable(comp2) (len, filter, f); // (A)
const countWhereOdd = countWhere_(odd);
// and run...
console.log(
countWhereOdd([1,2,3,4,5]) // 3
);
Please note that in line A we were forced to pass f explicitly. This is one of the drawbacks of composable against curried functions: Sometimes we need to pass the data explicitly. However, if you dislike point-free style, this is actually an advantage.
Conclusion
Making functions composable mitigates the following concerns:
aesthetic concerns (less frequent use of the curry pattern f(x) (y) (z)
performance penalties (far fewer function calls)
However, point #4 (readability) is only slightly improved (less point-free style) and point #3 (debugging) not at all.
While I am convinced that a fully curried approach is superior to the one presented here, I think composable higher order functions are worth thinking about. Just use them as long as you or your coworkers don't feel comfortable with proper currying.

lodash curry does not work on function returned by flow; lodash FP enough for FP?

Is the lodash flow function a real compose function, or is it something that looks like one, but is optimized to run fast and sacrifices the flexibility I'd expect? I expected flow to return a function I could curry, but instead it gave back a function that uses Javascript's arguments keyword. So curry can't tell that there are pending arguments, and it just gets invoked immediately.
Working intuitively enough:
var add = function(x, y) {
return x + y
};
var exclam = function(x) {
return x.toString() + "!";
}
exclam(1) // "1!"
add(1,2) // 3
var add1 = FP.curry(add)(1);
add1(4) // 5
var add1AndExclam = FP.flow([add1, exclam])
add1AndExclam(2) // "3!"
Non-intuitive result:
addAndExclam = FP.flow([add, exclam])
/*
function(){
var t=arguments,e=t[0];
if(i&&1==t.length&&yi(e)&&e.length>=200)return i.plant(e).value();
for(var u=0,t=r?n[u].apply(this,t):e;++u<r;)t=n[u].call(this,t);
return t
}
*/
addAndExclam(1,2) // "3!"
add1AndExclamV2 = FP.curry(addAndExclam)(1) // "NaN!"`
Is it overkill to look for another library to help with functional programming paradigms? Should I just whip up my own compose? I used lodash because it was already in my project. The documentation makes it look like flow should be lodash's compose.
I've also found it really difficult to curry the data argument in lodash's each (I wanted something like an eachMyArrayName shortcut). Whether I use curryRight or the lodash object placeholder convention.
Is lodash FP just for making lodash functions auto curriable? Or am I doing something wrong, and it is usable as the main functional programming helper?
Edit:
If I want to I can wrap the function like this, but it seems to defeat the purpose of meta programming to have boilerplate looking code.
add1AndExclamV2 = FP.curry(function(x, y) {
return addAndExclam(x, y)
})(1)
add1AndExclamV2(2)
"3!"`
This is just basic function composition. Lodash "flow" and Rambda "pipe" probably found it difficult to name these functions because they're not suitably generic. They're not "real" the same way you use the word real in the phrase "real compose function".
You can compose a binary function with a unary function using comp2 – the catch is, the "binary" function must be in curried form instead of taking a tuple
let f = x => y => ...
instead of
let f = (x,y) => ...
Recall that functional programming has its roots in the lambda calculus where there is no such thing as a function that takes anything other than 1 argument.
const curry = f => x => y => f (x,y)
const comp = f => g => x => f (g (x))
const comp2 = comp (comp) (comp)
var add = function(x, y) { return x + y };
var exclam = function(x) { return x.toString() + "!"; }
console.log(exclam (1)) // "1!"
console.log(add (1,2)) // 3
var add1 = curry (add) (1)
console.log(add1 (4)) // 5
var addAndExclam = comp2 (exclam) (curry (add))
console.log(addAndExclam (1) (2)) // "3!"
I encourage you to use the substitution model to see how the expression evaluates
Putting types on everything helps you reason about the program more effecitvely
// curry :: ((a,b) -> c) -> a -> b -> c
const curry = f => x => y => f (x,y)
// comp :: (b -> c) -> (a -> b) -> (a -> c)
const comp = f => g => x => f (g (x))
// comp2 :: (c -> d) -> (a -> b -> c) -> (a -> b -> d)
const comp2 = comp (comp) (comp)
// add :: (Number,Number) -> Number
var add = function(x, y) { return x + y };
// exclam :: Number -> String
var exclam = function(x) { return x.toString() + "!"; }
console.log(exclam (1)) // "1!"
console.log(add (1,2)) // 3
// add1 :: Number -> Number
var add1 = curry (add) (1)
console.log(add1 (4)) // 5
// addAndExlam :: Number -> Number -> String
var addAndExclam = comp2 (exclam) (curry (add))
console.log(addAndExclam (1) (2)) // "3!"
Regarding your comment:
I think if I wanted to compose a special function where one of the nested functions took two args, I would write it out
Good idea. If you find yourself looking around for a built-in procedure (provided by your language or some library), that should already be an indicator to you that you should try to write it out first. At least confirm with yourself that you're understanding your needs correctly.
This is perfectly acceptable
const addAndExclam = (x,y) => exclam (add (x,y))
And so is this
const addAndExclam = x => y => exclam (add (x,y))
If you later learn about comp2 and see that it could describe the code a little better, then you can implement it at that time
const addAndExclam = comp2 (exclam) (curry (add))
var myAdd = function(x, y) { return x + y; };
var exclam = function(x) { return x.toString() + '!'; };
var addSclam = pipe(myAdd, exclam);
addSclam(1,2); // "3!"
var add1Sclam = curry( addSclam )(1);
add1Sclam(500); // "501!"
It looks like ramda does what would have been intuitive to me. It adds another 1.2mb to my project, but I guess it could be used to more or less replace lodash.

n-ary curry in CoffeeScript

I was playing with CoffeeScript when I found myself writing the following lines and then looking at them in awe:
compose = (f, g) -> (x) -> f g x
curry = (f) -> (x) -> (y) -> f(x, y)
uncurry = (f) -> (x, y) -> (f x) y
How nice, did I think! Now, as an exercise, I thought I would generalize the curry and uncurry functions to n args, to obtain something similar to this:
curry2 = (f) -> (x) -> (y) -> f(x, y)
curry3 = (f) -> (x) -> (y) -> (z) -> f(x, y, z)
curry4 = (f) -> (x) -> (y) -> (z) -> (t) -> f(x, y, z, t)
And the same thing for uncurry:
uncurry2 = (f) -> (x, y) -> (f x) y
uncurry3 = (f) -> (x, y, z) -> ((f x) y) z
uncurry4 = (f) -> (x, y, z, t) -> (((f x) y) z) t
Writing the n-ary uncurry was not very hard:
uncurry = (n) -> (f) -> (args...) ->
if n == 1
f args[0]
else
((uncurry n - 1) f args.shift()) args...
On the other hand, I can't figure out how to get the n-ary curry to work. I thought of implementing first a curry_list function that is the generalization of this suite:
curry_list2 = (f) -> (x) -> [x, y]
curry_list3 = (f) -> (x) -> (z) -> [x, y, z]
curry_list4 = (f) -> (x) -> (z) -> (t) -> [x, y, z, t]
Here's the implementation:
curry_list = (n) ->
curry_list_accum = (n, accum) ->
if n
(x) ->
accum.push x
curry_list_accum n - 1, accum
else
accum
curry_list_accum n, []
And then I would just compose curry_list with function application to obtain currying. That's what I tried to do:
curry = (n) ->
apply_helper = (f) -> (args) -> f args...
(f) -> compose (apply_helper f), (curry_list n)
But for some reason, it does not work. For exemple, trying to evaluate
curry(3)((a,b,c) -> a + b + c)(1)(2)(3)
yields the following error:
Function.prototype.apply: Arguments list has wrong type
Now after jotting some more notes I understand that trying to compose f with curry_list is incorrect. I do have the intuition that what I'm looking for is something that looks like this composition, but is not exactly that. Am I correct in thinking that?
Finally, what would be a correct implementation?
You are returning the composed function after curry(3)((a,b,c) -> a + b + c), not the accumulator.
That means ((args) -> f args...) is receiving a function as argument, your code doesn't wait until the argument list is complete to call f.
Maybe implement this without composition?
accumulator = (n, accum, f) ->
return f accum... if n is 0
(x) ->
accum.push x
accumulator n - 1, accum, f
curry = (n) ->
(f) -> accumulator n, [], f
curry(3)((a,b,c) -> a + b + c)(1)(2)(3) # 6
I don't think it gets any simpler than this:
Function::curry = (n) ->
if n is 1 then # else (x) => (=> # x, arguments...).curry(n-1)
Basically if the arity requested is greater than 1 then it consumes an argument and returns another function and constructs a ladder of functions along the way. It does so until the arity is 1, in which case it climbs up the ladder of functions it created. The ladder adds the consumed arguments into a list until the function at the top of the ladder, which is the user provided one, gets called.
Here's some tests I wrote in case you're interested:
add3 = ((a,b,c) -> a+b+c).curry 3
add3_1 = add3 1
add3_1_2 = add3_1 2
console.log add3_1(4)(5) is 10
console.log add3_1(4)(6) is 11
console.log add3_1_2(4) is 7
console.log add3_1(5)(5) is 11
It doesn't look to me like composition. The last curry implementation you have seems to make no distinction between the function to be curried and the arguments to that function, whereas it would seem that such a distinction is rather important. How about something like this?
curry = (n, f) ->
acc = []
helper = (x) ->
acc.push x
if acc.length is n then f acc... else helper
A related generalization is presented in Partial with Free Variables.
I got really interested in solving this, so I wrote this up. It probably needs a few tweaks, but it works awesomely as far as I have tested. Basically just call f.curry() which returns partially applied functions in succession.. until you call it with the last argument that it takes, which is when that partial calls the one before it and so on, all the way back down the the original f.
partial = (f, args1...) -> (args2...) ->
f.apply #, args1.concat args2
partial$ = (f, args) ->
partial.apply #, [f].concat args
Function::curry = (args...) ->
curry$ = (n, f, args...) ->
curry$$ = (n, f, args...) ->
if n > args.length
partial curry$$, (n - args.length), (partial$ f, args)
else f args
curry$$ (n - args.length), (partial$ f, args)
curry$.apply #, [#length, #].concat args
Now we can do things like this:
twoToThe = Math.pow.curry 2
32 == twoToThe 5
32 == Math.pow.curry()(2)(5)
32 == Math.pow.curry()(2, 5)
32 == Math.pow.curry(2, 5)
32 == Math.pow.curry(2)(5)
# And just for laughs:
32 == Math.pow.curry()()()(2)()()()(5)

javascript: recursive anonymous function?

Let's say I have a basic recursive function:
function recur(data) {
data = data+1;
var nothing = function() {
recur(data);
}
nothing();
}
How could I do this if I have an anonymous function such as...
(function(data){
data = data+1;
var nothing = function() {
//Something here that calls the function?
}
nothing();
})();
I'd like a way to call the function that called this function... I've seen scripts somewhere (I can't remember where) that can tell you the name of a function called, but I can't recall any of that information right now.
You can give the function a name, even when you're creating the function as a value and not a "function declaration" statement. In other words:
(function foo() { foo(); })();
is a stack-blowing recursive function. Now, that said, you probably don't may not want to do this in general because there are some weird problems with various implementations of Javascript. (note — that's a fairly old comment; some/many/all of the problems described in Kangax's blog post may be fixed in more modern browsers.)
When you give a name like that, the name is not visible outside the function (well, it's not supposed to be; that's one of the weirdnesses). It's like "letrec" in Lisp.
As for arguments.callee, that's disallowed in "strict" mode and generally is considered a bad thing, because it makes some optimizations hard. It's also much slower than one might expect.
edit — If you want to have the effect of an "anonymous" function that can call itself, you can do something like this (assuming you're passing the function as a callback or something like that):
asyncThingWithCallback(params, (function() {
function recursive() {
if (timeToStop())
return whatever();
recursive(moreWork);
}
return recursive;
})());
What that does is define a function with a nice, safe, not-broken-in-IE function declaration statement, creating a local function whose name will not pollute the global namespace. The wrapper (truly anonymous) function just returns that local function.
People talked about the Y combinator in comments, but no one wrote it as an answer.
The Y combinator can be defined in javascript as follows: (thanks to steamer25 for the link)
var Y = function (gen) {
return (function(f) {
return f(f);
}(function(f) {
return gen(function() {
return f(f).apply(null, arguments);
});
}));
}
And when you want to pass your anonymous function:
(Y(function(recur) {
return function(data) {
data = data+1;
var nothing = function() {
recur(data);
}
nothing();
}
})());
The most important thing to note about this solution is that you shouldn't use it.
U combinator
By passing a function to itself as an argument, a function can recur using its parameter instead of its name! So the function given to U should have at least one parameter that will bind to the function (itself).
In the example below, we have no exit condition, so we will just loop indefinitely until a stack overflow happens
const U = f => f (f) // call function f with itself as an argument
U (f => (console.log ('stack overflow imminent!'), U (f)))
We can stop the infinite recursion using a variety of techniques. Here, I'll write our anonymous function to return another anonymous function that's waiting for an input; in this case, some number. When a number is supplied, if it is greater than 0, we will continue recurring, otherwise return 0.
const log = x => (console.log (x), x)
const U = f => f (f)
// when our function is applied to itself, we get the inner function back
U (f => x => x > 0 ? U (f) (log (x - 1)) : 0)
// returns: (x => x > 0 ? U (f) (log (x - 1)) : 0)
// where f is a reference to our outer function
// watch when we apply an argument to this function, eg 5
U (f => x => x > 0 ? U (f) (log (x - 1)) : 0) (5)
// 4 3 2 1 0
What's not immediately apparent here is that our function, when first applied to itself using the U combinator, it returns a function waiting for the first input. If we gave a name to this, can effectively construct recursive functions using lambdas (anonymous functions)
const log = x => (console.log (x), x)
const U = f => f (f)
const countDown = U (f => x => x > 0 ? U (f) (log (x - 1)) : 0)
countDown (5)
// 4 3 2 1 0
countDown (3)
// 2 1 0
Only this isn't direct recursion – a function that calls itself using its own name. Our definition of countDown does not reference itself inside of its body and still recursion is possible
// direct recursion references itself by name
const loop = (params) => {
if (condition)
return someValue
else
// loop references itself to recur...
return loop (adjustedParams)
}
// U combinator does not need a named reference
// no reference to `countDown` inside countDown's definition
const countDown = U (f => x => x > 0 ? U (f) (log (x - 1)) : 0)
How to remove self-reference from an existing function using U combinator
Here I'll show you how to take a recursive function that uses a reference to itself and change it to a function that employs the U combinator to in place of the self reference
const factorial = x =>
x === 0 ? 1 : x * factorial (x - 1)
console.log (factorial (5)) // 120
Now using the U combinator to replace the inner reference to factorial
const U = f => f (f)
const factorial = U (f => x =>
x === 0 ? 1 : x * U (f) (x - 1))
console.log (factorial (5)) // 120
The basic replacement pattern is this. Make a mental note, we will be using a similar strategy in the next section
// self reference recursion
const foo = x => ... foo (nextX) ...
// remove self reference with U combinator
const foo = U (f => x => ... U (f) (nextX) ...)
Y combinator
related: the U and Y combinators explained using a mirror analogy
In the previous section we saw how to transform self-reference recursion into a recursive function that does not rely upon a named function using the U combinator. There's a bit of an annoyance tho with having to remember to always pass the function to itself as the first argument. Well, the Y-combinator builds upon the U-combinator and removes that tedious bit. This is a good thing because removing/reducing complexity is the primary reason we make functions
First, let's derive our very own Y-combinator
// standard definition
const Y = f => f (Y (f))
// prevent immediate infinite recursion in applicative order language (JS)
const Y = f => f (x => Y (f) (x))
// remove reference to self using U combinator
const Y = U (h => f => f (x => U (h) (f) (x)))
Now we will see how it's usage compares to the U-combinator. Notice, to recur, instead of U (f) we can simply call f ()
const U = f => f (f)
const Y = U (h => f => f (x => U (h) (f) (x)))
Y (f => (console.log ('stack overflow imminent!'), f ()))
Now I'll demonstrate the countDown program using Y – you'll see the programs are almost identical but the Y combinator keeps things a bit cleaner
const log = x => (console.log (x), x)
const U = f => f (f)
const Y = U (h => f => f (x => U (h) (f) (x)))
const countDown = Y (f => x => x > 0 ? f (log (x - 1)) : 0)
countDown (5)
// 4 3 2 1 0
countDown (3)
// 2 1 0
And now we'll see factorial as well
const U = f => f (f)
const Y = U (h => f => f (x => U (h) (f) (x)))
const factorial = Y (f => x =>
x === 0 ? 1 : x * f (x - 1))
console.log (factorial (5)) // 120
As you can see, f becomes the mechanism for recursion itself. To recur, we call it like an ordinary function. We can call it multiple times with different arguments and the result will still be correct. And since it's an ordinary function parameter, we can name it whatever we like, such as recur below -
const U = f => f (f)
const Y = U (h => f => f (x => U (h) (f) (x)))
const fibonacci = Y (recur => n =>
n < 2 ? n : recur (n - 1) + (n - 2))
console.log (fibonacci (10)) // 55
U and Y combinator with more than 1 parameter
In the examples above, we saw how we can loop and pass an argument to keep track of the "state" of our computation. But what if we need to keep track of additional state?
We could use compound data like an Array or something...
const U = f => f (f)
const Y = U (h => f => f (x => U (h) (f) (x)))
const fibonacci = Y (f => ([a, b, x]) =>
x === 0 ? a : f ([b, a + b, x - 1]))
// starting with 0 and 1, generate the 7th number in the sequence
console.log (fibonacci ([0, 1, 7]))
// 0 1 1 2 3 5 8 13
But this is bad because it's exposing internal state (counters a and b). It would be nice if we could just call fibonacci (7) to get the answer we want.
Using what we know about curried functions (sequences of unary (1-paramter) functions), we can achieve our goal easily without having to modify our definition of Y or rely upon compound data or advanced language features.
Look at the definition of fibonacci closely below. We're immediately applying 0 and 1 which are bound to a and b respectively. Now fibonacci is simply waiting for the last argument to be supplied which will be bound to x. When we recurse, we must call f (a) (b) (x) (not f (a,b,x)) because our function is in curried form.
const U = f => f (f)
const Y = U (h => f => f (x => U (h) (f) (x)))
const fibonacci = Y (f => a => b => x =>
x === 0 ? a : f (b) (a + b) (x - 1)) (0) (1)
console.log (fibonacci (7))
// 0 1 1 2 3 5 8 13
This sort of pattern can be useful for defining all sorts of functions. Below we'll see two more functions defined using the Y combinator (range and reduce) and a derivative of reduce, map.
const U = f => f (f)
const Y = U (h => f => f (x => U (h) (f) (x)))
const range = Y (f => acc => min => max =>
min > max ? acc : f ([...acc, min]) (min + 1) (max)) ([])
const reduce = Y (f => g => y => ([x,...xs]) =>
x === undefined ? y : f (g) (g (y) (x)) (xs))
const map = f =>
reduce (ys => x => [...ys, f (x)]) ([])
const add = x => y => x + y
const sq = x => x * x
console.log (range (-2) (2))
// [ -2, -1, 0, 1, 2 ]
console.log (reduce (add) (0) ([1,2,3,4]))
// 10
console.log (map (sq) ([1,2,3,4]))
// [ 1, 4, 9, 16 ]
IT'S ALL ANONYMOUS OMG
Because we're working with pure functions here, we can substitute any named function for its definition. Watch what happens when we take fibonacci and replace named functions with their expressions
/* const U = f => f (f)
*
* const Y = U (h => f => f (x => U (h) (f) (x)))
*
* const fibonacci = Y (f => a => b => x => x === 0 ? a : f (b) (a + b) (x - 1)) (0) (1)
*
*/
/*
* given fibonacci (7)
*
* replace fibonacci with its definition
* Y (f => a => b => x => x === 0 ? a : f (b) (a + b) (x - 1)) (0) (1) (7)
*
* replace Y with its definition
* U (h => f => f (x => U (h) (f) (x))) (f => a => b => x => x === 0 ? a : f (b) (a + b) (x - 1)) (0) (1) (7)
//
* replace U with its definition
* (f => f (f)) U (h => f => f (x => U (h) (f) (x))) (f => a => b => x => x === 0 ? a : f (b) (a + b) (x - 1)) (0) (1) (7)
*/
let result =
(f => f (f)) (h => f => f (x => h (h) (f) (x))) (f => a => b => x => x === 0 ? a : f (b) (a + b) (x - 1)) (0) (1) (7)
console.log (result) // 13
And there you have it – fibonacci (7) calculated recursively using nothing but anonymous functions
It may be simplest to use an "anonymous object" instead:
({
do: function() {
console.log("don't run this ...");
this.do();
}
}).do();
Your global space is completely unpolluted. It's pretty straightforward. And you can easily take advantage of the object's non-global state.
You can also use ES6 object methods to make the syntax more concise.
({
do() {
console.log("don't run this ...");
this.do();
}
}).do();
I would not do this as an inline function. It's pushing against the boundaries of good taste and doesn't really get you anything.
If you really must, there is arguments.callee as in Fabrizio's answer. However this is generally considered inadvisable and is disallowed in ECMAScript Fifth Edition's ‘strict mode’. Although ECMA 3 and non-strict-mode are not going away, working in strict mode promises more possible language optimisations.
One can also use a named inline function:
(function foo(data){
data++;
var nothing = function() {
foo(data);
}
nothing();
})();
However named inline function expressions are also best avoided, as IE's JScript does some bad things to them. In the above example foo incorrectly pollutes the parent scope in IE, and the parent foo is a separate instance to the foo seen inside foo.
What's the purpose of putting this in an inline anonymous function? If you just want to avoid polluting the parent scope, you can of course hide your first example inside another self-calling-anonymous-function (namespace). Do you really need to create a new copy of nothing each time around the recursion? You might be better off with a namespace containing two simple mutually-recursive functions.
(function(data){
var recursive = arguments.callee;
data = data+1;
var nothing = function() {
recursive(data)
}
nothing();
})();
You could do something like:
(foo = function() { foo(); })()
or in your case:
(recur = function(data){
data = data+1;
var nothing = function() {
if (data > 100) return; // put recursion limit
recur(data);
}
nothing();
})(/* put data init value here */ 0);
When you declare an anonymous function like this:
(function () {
// Pass
}());
Its considered a function expression and it has an optional name (that you can use to call it from within itself. But because it's a function expression (and not a statement) it stays anonymous (but has a name that you can call). So this function can call itself:
(function foo () {
foo();
}());
foo //-> undefined
Why not pass the function to the functio itself ?
var functionCaller = function(thisCaller, data) {
data = data + 1;
var nothing = function() {
thisCaller(thisCaller, data);
};
nothing();
};
functionCaller(functionCaller, data);
In certain situations you have to rely on anonymous functions. Given is a recursive map function:
const map = f => acc => ([head, ...tail]) => head === undefined
? acc
: map (f) ([...acc, f(head)]) (tail);
const sqr = x => x * x;
const xs = [1,2,3,4,5];
console.log(map(sqr) ([0]) (xs)); // [0] modifies the structure of the array
Please note that map must not modify the structure of the array. So the accumulator acc needn't to be exposed. We can wrap map into another function for instance:
const map = f => xs => {
let next = acc => ([head, ...tail]) => head === undefined
? acc
: map ([...acc, f(head)]) (tail);
return next([])(xs);
}
But this solution is quite verbose. Let's use the underestimated U combinator:
const U = f => f(f);
const map = f => U(h => acc => ([head, ...tail]) => head === undefined
? acc
: h(h)([...acc, f(head)])(tail))([]);
const sqr = x => x * x;
const xs = [1,2,3,4,5];
console.log(map(sqr) (xs));
Concise, isn't it? U is dead simple but has the disadvantage that the recursive call gets a bit obfuscated: sum(...) becomes h(h)(...) - that's all.
I am not sure if the answer is still required but this can also be done using delegates created using function.bind:
var x = ((function () {
return this.bind(this, arguments[0])();
}).bind(function (n) {
if (n != 1) {
return n * this.bind(this, (n - 1))();
}
else {
return 1;
}
}))(5);
console.log(x);
This does not involve named functions or arguments.callee.
With ES2015 we can play around a bit with the syntax and abuse default parameters and thunks. The latter are just functions without any arguments:
const applyT = thunk => thunk();
const fib = n => applyT(
(f = (x, y, n) => n === 0 ? x : f(y, x + y, n - 1)) => f(0, 1, n)
);
console.log(fib(10)); // 55
// Fibonacci sequence: 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55...
Please note that f is a parameter with the anonymous function (x, y, n) => n === 0 ? x : f(y, x + y, n - 1) as its default value. When f is invoked by applyT this invocation must take place without arguments, so that the default value is used. The default value is a function and hence f is a named function, which can call itself recursively.
Like bobince wrote, simply name your function.
But, I'm guessing you also want to pass in an initial value and stop your function eventually!
var initialValue = ...
(function recurse(data){
data++;
var nothing = function() {
recurse(data);
}
if ( ... stop condition ... )
{ ... display result, etc. ... }
else
nothing();
}(initialValue));
working jsFiddle example (uses data += data for fun)
i needed (or rather, wanted) an one-liner anonymous function to walk its way up an object building up a string, and handled it like this:
var cmTitle = 'Root' + (function cmCatRecurse(cmCat){return (cmCat == root) ? '' : cmCatRecurse(cmCat.parent) + ' : ' + cmCat.getDisplayName();})(cmCurrentCat);
which produces a string like 'Root : foo : bar : baz : ...'
Another answer which does not involve named function or arguments.callee
var sum = (function(foo,n){
return n + foo(foo,n-1);
})(function(foo,n){
if(n>1){
return n + foo(foo,n-1)
}else{
return n;
}
},5); //function takes two argument one is function and another is 5
console.log(sum) //output : 15
This is a rework of jforjs answer with different names and a slightly modified entry.
// function takes two argument: first is recursive function and second is input
var sum = (function(capturedRecurser,n){
return capturedRecurser(capturedRecurser, n);
})(function(thisFunction,n){
if(n>1){
return n + thisFunction(thisFunction,n-1)
}else{
return n;
}
},5);
console.log(sum) //output : 15
There was no need to unroll the first recursion. The function receiving itself as a reference harkens back to the primordial ooze of OOP.
This is a version of #zem's answer with arrow functions.
You can use the U or the Y combinator. Y combinator being the simplest to use.
U combinator, with this you have to keep passing the function:
const U = f => f(f)
U(selfFn => arg => selfFn(selfFn)('to infinity and beyond'))
Y combinator, with this you don't have to keep passing the function:
const Y = gen => U(f => gen((...args) => f(f)(...args)))
Y(selfFn => arg => selfFn('to infinity and beyond'))
Yet another Y-combinator solution, using rosetta-code link (I think somebody previously mentioned the link somewhere on stackOverflow.
Arrows are for anonymous functions more readable to me:
var Y = f => (x => x(x))(y => f(x => y(y)(x)));
I don't suggest doing this in any practical use-case, but just as a fun exercise, you can actually do this using a second anonymous function!
(f => f(f))(f => {
data = data+1;
var nothing = function() {
f();
}
nothing(f);
});
The way this works is that we're passing the anonymous function as an argument to itself, so we can call it from itself.
by using arguments.callee(). For more details visit this url: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Functions#scope_and_the_function_stack
(function(data){
data = data+1;
var nothing = function() {
arguments.callee() // this calls the function itself
}
nothing();
})();
This may not work everywhere, but you can use arguments.callee to refer to the current function.
So, factorial could be done thus:
var fac = function(x) {
if (x == 1) return x;
else return x * arguments.callee(x-1);
}

Categories

Resources