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

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)
}
主站蜘蛛池模板: 广饶县| 伊宁县| 汝州市| 苏尼特右旗| 海城市| 铜川市| 长泰县| 恩施市| 冕宁县| 台东市| 宿迁市| 宁化县| 兰西县| 巴林左旗| 永兴县| 琼海市| 乌恰县| 滦平县| 绥宁县| 佛山市| 林芝县| 武义县| 金溪县| 金溪县| 定远县| 罗源县| 济源市| 土默特左旗| 安乡县| 驻马店市| 临安市| 嘉定区| 小金县| 驻马店市| 武城县| 娱乐| 嘉兴市| 台中市| 桐梓县| 东光县| 鄂州市|