Explore C # 's recursive APs and CPS

Source: Internet
Author: User

Accumulator Delivery Mode (accumulator passing style)

Tail recursion is optimized so that the stack can use recursive functions as a normal function call without saving the last return address/status value.

Recursion actually relies on the last value to find the next value. If we can save the last value, pass it in the next call, not directly reference the value returned by the function. Thus the stack is released, and the end recursive optimization is achieved.

Here we added an ACC parameter that stores the last value, which is passed in the next call.

static int accumulate (int acc, int n)

{

if (n = = 0)

Return to ACC;

return Accumulate (ACC * n, n-1);

}

When using accumulate recursion, we only need to use the last return value. The call is as follows:

var ac = accumulate (1, 20);

Use lambda expressions to implement tail-recursive factorial:

static int Accumulatebylambda (int x)

{

Func accumulate = null;

accumulate = (ACC, n) => n = 0? Acc:accumulate (ACC * n, n-1);

return accumulate (1, x);

}

CPS function

CPS full name continuation passing style, Chinese general translation for subsequent delivery mode.

static int Times3 (int x)

{

return x * 3;

}

Console.WriteLine (Times3 (5));

The above function multiplies the input value by 3, which we typically write in general. In fact, we can also use the C # syntax of the return function to construct the nesting method, and turn the call of the function into the call chain Times3 (3) (5).

This approach is more intuitive and normal in math or functional programming, but not so intuitive in the directive language C #.

The term successor (continuation) in the CPS refers to the remainder of the calculation, similar to the TIMES3 (3) (5) Red part.

For example, an expression A * (B+C) operation has several computational steps. C # can be written as the following function to represent:

Console.WriteLine (Mult (A,add (b,c))

Action steps are as follows:

B is added with C.

Multiply the result by a.

Output results.

When you perform 1 steps, the following actions are 2, 3. When you perform 2 steps, the next operation is 3. Use CPS mode to transform the TIMES3 function:

static void Times3cps (int x, Action continuation)

{

Continuation (x * 3);

}

Times3cps (5, (Reslut) => Console.WriteLine (result));

We added a function parameter representing the successor Operation 3, which is the CPS function, which is passed after the call.

CPS Transform

After you know the CPS function, then look at the CPS transformation in detail.

Console.WriteLine (Times3 (5));

CPS Transform

Times3cps (5, (Reslut) => Console.WriteLine (result));

The above Times3 function is called CPS conversion from the direct tune to the process of using subsequent delivery operations.

such as the conversion of the 1:max function

static int Max (int n, int m)

{

if (n > M)

return n;

Else

return m;

}

Console.WriteLine (Max (3, 4));

We convert this max function into CPS mode, which requires the following steps:

1: Return value modified to void

2: Add an additional type parameter action,t is the original return type.

3: Replace all return declarations with subsequent action expression arguments.

static void Max (int n, int m, Action k)

{

if (n > M)

K (n);

Else

K (m);

}

Max (3, 4, X => Console.WriteLine (x));

For example 2: If there are 3 functions main, F, G,main call F, F call G.

Console.WriteLine (F (1) + 1);

static int F (int n)

{

return G (n + 1) + 1;

}

static int G (int n)

{

return n + 1;

}

We convert f and G to CPS style, and the same conversion steps as the Max function:

F (1, x => Console.WriteLine (x + 1));

static void F (int n, Action k)

{

G (n + 1, x => K (x + 1));

}

static void G (int n, Action k)

{

K (n + 1);

}

CPS Tail Recursion

This is the traditional recursive factorial:

static int factorial (int n)

{

if (n = = 0)

return 1;

Else

return n * factorial (n-1);

}

Using the same procedure, convert recursion to CPS tail recursion:

Factorial (5, X => Console.WriteLine (x));

static void factorial (int n, Action continuation)

{

if (n = = 0)

Continuation (1);

Else

Factorial (n-1, x => continuation (n * x));

}

Lao Zhao-tail recursion and continuation

"Calculates the factorial of N and passes the result into the continuation method and returns", which is, "calculates the factorial of the n-1 and multiplies the result with N, and then calls the continuation method." In order to implement the logic of "multiplying the result with N and then invoking the continuation method", the code constructs an anonymous method and passes in the factorial method again.

Summarize

The CPS model is very powerful and is used in many ways, such as the CPS-style parser combination in compiler implementations, and the callback after function completion. It can also be said that the original control operation within the program, using CPS method to extract the exposure to the programmer, such as the text of the example.

Note : For more wonderful tutorials, please pay attention to the Triple Web Design Tutorial section,

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.