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

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)
}
主站蜘蛛池模板: 惠来县| 永泰县| 岑溪市| 资中县| 新化县| 木兰县| 临沂市| 富裕县| 疏勒县| 正安县| 汨罗市| 贵溪市| 宝鸡市| 阳西县| 长治县| 十堰市| 青河县| 明星| 津市市| 石屏县| 灌南县| 西平县| 隆安县| 萨嘎县| 大埔区| 虎林市| 韶关市| 射洪县| 兴仁县| 台南县| 大庆市| 绥棱县| 武川县| 九台市| 车险| 都匀市| 乐清市| 区。| 东丽区| 南雄市| 甘孜|