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
  • 1
    $\begingroup$ Mma also has the Identity function, so you can also do id=Identity. $\endgroup$
    – evanb
    May 12, 2017 at 5:07

1 Answer 1

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$
4
  • $\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, 2017 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, 2017 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, 2017 at 3:39
  • $\begingroup$ @WReach Hehe.. yes. I was unwilling to go that path of the devil :) $\endgroup$
    – halirutan
    May 12, 2017 at 3:41

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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