5
$\begingroup$

I am trying to create some functions that I want to comfortably compose together using the pure functions.

The functions were originally written in $\lambda$-expressions so I would like to keep the format as close to it as possible. They are

  • ${\rm id}:=(\lambda x . x)$

  • ${\rm almost\$factorial}:=(\lambda f.(\lambda n. \text{If } (n=0) \text{ then } 1 \text{ else } n*f(n-1)))$

  • ${\rm factorial0}:= {\rm almost\$factorial} ({\rm id})$

I realized that I can write

id:= (#)& 

for ${\rm id}$.

So id[x] gives me x, which is what I expected. However, I'm at lost on how to write $almost-factorial$. I tried

almost$factorial := If[#1==0, 1, #1*(#2[#1 - 1])]&

But it only works when it takes two arguments at once. I would to be able to define almost$factorial as a pure function that takes only one argument and outputs another pure function, which I can apply.

almost$factorial[id] [0] = 1. 

Is this possible to do in Mathematica?

$\endgroup$
  • 1
    $\begingroup$ Mma also has the Identity function, so you can also do id=Identity. $\endgroup$ – evanb May 12 '17 at 5:07
8
$\begingroup$

Here are two ways. First with pure functions:

idP = Function[x, x];
almostFactorialP = Function[f, Function[n, If[n == 0, 1, n*f[n - 1]]]]

almostFactorialP[idP][4]
(* 12 *)

In general, this is the same method you tried with the Slot (#) notation. Unfortunately, in a construct like (#+(#+#&))& there is no way to refer to the outer # in the inner function or fill the inner slots. This is the reason I used Function explicitly.

Another way is to use SubValues:

id[x_] := x;
almostFactorial[f_][n_] := If[n == 0, 1, n*f[n - 1]];

almostFactorial[id][4]
(* 12 *)
$\endgroup$
  • $\begingroup$ Thank you. The first one is the one I needed and it felt the most similar to the lambda expressions given. I'm guessing it's not doable with the # shortcuts mentioned in my post? $\endgroup$ – BeerR May 12 '17 at 2:46
  • 2
    $\begingroup$ @BeerR When you try it in the shorter # form, you will get into trouble as you cannot distinguish which # refers to your outer lambda expression. This is why you have to use the longer, named-argument version. $\endgroup$ – halirutan May 12 '17 at 2:50
  • 3
    $\begingroup$ +1 Just for fun: almostFactorialNoWay = #0[[0]][If[#2[1]==0, 1, #2[1] * #[#2[1] - 1]]]&[#, Slot]&. Although we might as well switch to full-on Church-coded lambda calculus once we start going down that path ;D $\endgroup$ – WReach May 12 '17 at 3:39
  • $\begingroup$ @WReach Hehe.. yes. I was unwilling to go that path of the devil :) $\endgroup$ – halirutan May 12 '17 at 3:41

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.