4
$\begingroup$

I am very confused about how can i use currying to write a tail recursive function for summing factorials within a certain bound or summing the bounds i.e. given [1,5] i should be getting 1!+2!+3!+4!+5! and for summing bounds 1+2+3+4+5. How can i construct two elegant functions using currying.

My code currently looks like this:

factorial[n_] := (loopfact[n, acc_] := If[n == 0, acc, loopfact[n - 1, acc*n]];
Return@loopfact[n, 1]);

sum[a_, b_, acc_] := Block[{x, ac}, x = a; ac = acc;
loop[x_, ac_] := If[x > b, ac, loop[x + 1, ac + factorial[x]]];
loop[x, ac]]

sum[0, 5, 0] (* using the function above *)
(* 154 *)

sum[a_, b_, acc_] := Module[{x, ac}, x = a; ac = acc;
loop[x_, ac_] := If[x > b, ac, loop[x + 1, ac + # &@x]];
loop[x, ac]]

sum[0, 50, 0] (* using the second function definition *)
(* 1275 *)

Also could someone kindly explain to me how currying works in Mathematica. Thanks !

$\endgroup$
  • $\begingroup$ Is there a reason why you can't use Plus @@ Factorial /@ Range[1, 5]? $\endgroup$ – Edmund Mar 25 '16 at 0:06
  • $\begingroup$ I am aware of that. just for the purpose of knowing how to morph my code from higher order functions to employing currying. Also, because i wish to understand how currying works in mathematica $\endgroup$ – Ali Hashmi Mar 25 '16 at 0:27
4
$\begingroup$

If you are more interested in currying than tail-recursion, this is not the answer you want. However, I don't think currying, and certainly not your approach to currying, is very suited to Mathematica. (It will be interesting if Leonid Shifrin or someone else of his level of expertise will step in a show that I'm wrong).

If tail-recursive is really the focus of your question, then I recommend a Scheme style approach with tail-recursive helper functions. This is very clean stylistically (no If, but only pattern matching on arguments).

First the factorial.

g[1, val_] = val;
g[k_ /; k > 1, val_] := g[k - 1, k val]
f[1] = 1;
f[k_Integer /; k > 1] := g[k - 1, k]

Now the summation.

s[a_, a_, val_] := val + f[a]
s[a_, b_, val_] := s[a, b - 1, val + f[b]]
sum[a_Integer /; a > 0, b_Integer] /; b >= a := s[a, b, 0]

sum[1, 5] == Plus @@ Factorial /@ Range[1, 5]

True

Edge case.

sum[10, 10] == Factorial[10]

True

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.