官术网_书友最值得收藏!

Continuation Passing Style

The preceding code, in which you call a function but also pass another function that is to be executed when the input/output operation is finished, can be considered a case of CPS - Continuation Passing Style. What is this way of coding? A way of putting it, is by thinking about this question: how would you program if using the return statement was forbidden?

At first glance, this may appear to be an impossible situation. We can get out of our fix, however, if we grant this: you are allowed to pass a callback to the called function, so when that procedure is ready to return to the caller, instead of actually returning, it shall invoke the passed callback. In these terms, the callback provides the called function with the way to continue the process, and thus the name Continuation. We won't get into this now, but in Chapter 9, Designing Functions - Recursion, we will study it in depth. In particular, CPS will help to avoid an important recursion restriction, as we'll see.

Working out how to use continuations is sometimes challenging, but always possible. An interesting advantage of this way of coding, is that by specifying yourself how the process is going to continue, you can go beyond all the usual structures (if, while, return, and so on) and implement whatever mechanisms you may want. This can be very useful in some kinds of problems, where the process isn't necessarily linear. Of course, this can also lead to you inventing any kind of control structures, far worse than the possible usage of GOTO statements that you might imagine! Figure 3.1 shows the dangers of that practice!

Figure 3.1: What's the worse that could happen if you start messing with the program flow?
(Note: This XKCD comic is available online at https://xkcd.com/292/.)

You are not limited to passing a single continuation. As with promises, you can provide two or more alternate callbacks. And this, by the way, can provide a solution to another problem: how would you work with exceptions? If we simply allowed a function to throw an error, it would be an implied return to the caller -- and we don't want this. The way out is to provide an alternative callback (that is, a different continuation) to be used whenever an exception would be thrown (in Chapter 12, Building Better Containers - Functional Data Types, we'll find another solution, with Monads):

function doSomething(a, b, c, normalContinuation, errorContinuation) {
let r = 0;
// ... do some calculations involving a, b, and c,
// and store the result in r

// if an error happens, invoke:
// errorContinuation("description of the error")

// otherwise, invoke:
// normalContinuation(r)
}
主站蜘蛛池模板: 和顺县| 康定县| 靖远县| 白山市| 连南| 清苑县| 揭阳市| 正定县| 都匀市| 象州县| 娱乐| 江山市| 石棉县| 郁南县| 都安| 年辖:市辖区| 冕宁县| 砀山县| 修水县| 定西市| 伊通| 佛冈县| 信丰县| 新余市| 隆尧县| 肃宁县| 东城区| 将乐县| 潢川县| 卢湾区| 营口市| 盐源县| 仙桃市| 葫芦岛市| 安新县| 大理市| 永康市| 平度市| 乌兰县| 普定县| 筠连县|