Lascia che Eric Lippert risponda a questo:
The obvious question at this point is: if CPS is so awesome then why
don’t we use it all the time? Why have most professional developers
never heard of it, or, those who have, think of it as something only
those crazy Scheme programmers do?
First of all, it is simply hard for most people who are used to
thinking about subroutines, loops, try-catch-finally and so on to
reason about delegates being used for control flow in this way. I am
reviewing my notes on CPS from CS442 right now and I see that in 1995
I wrote down a profQUOTE: “With continuations you have to sort of
stand on your head and pull yourself inside out”. Professor Duggan (*)
was absolutely correct in saying that. Recall from a couple days ago
that our tiny little example of CPS transformation of the C#
expression M(B()?C():D()) involved four lambdas. Not everyone is good
at reading code that uses higher-order functions. It imposes a large
cognitive burden.
Moreover: one of the nice things about having specific control flow
statements baked in to a language is that they let your code clearly
express the meaning of the control flow while hiding the mechanisms –
the call stacks and return addresses and exception handler lists and
protected regions and so on. Continuations make the mechanisms of
control flow explicit in the structure of the code. All that emphasis
on mechanism can overwhelm the meaning of the code.
In il prossimo articolo , spiega come l'asincronia e le continuazioni siano esattamente equivalenti l'una all'altra, e fa una dimostrazione di prendere una semplice, (ma bloccante) operazione di rete sincrona e riscriverla in uno stile asincrono, assicurandosi che per coprire tutti i trucchi nascosti che devono essere coperti al fine di farlo bene. Si trasforma in un pasticcio di codice massiccio . Il suo riassunto alla fine:
Holy goodness, what a godawful mess we’ve made. We've expanded two
lines of perfectly clear code into two dozen lines of the most
godawful spaghetti you've ever seen. And of course it still doesn’t
even compile because the labels aren’t in scope and we have a definite
assignment error. We;d still need to further rewrite the code to fix
those problems.
Remember what I was saying about the pros and cons of CPS?
- PRO: Arbitrarily complex and interesting control flows can be built out of simple parts – check.
- CON: The reification of control flow via continuations is hard to read and hard to reason about – check.
- CON: The code that represents the mechanisms of control flow completely overwhelms the meaning of the code – check.
- CON: The transformation of ordinary code control flow into CPS is the kind of thing that compilers are good at, and almost no one else
is – check.
This is not some intellectual exercise. Real people end up writing
code morally equivalent to the above all the time when they deal with
asynchrony. And, ironically, even as processors have gotten faster and
cheaper, we spend more and more of our time waiting for stuff that
isn’t processor-bound. In many programs, much of the time spent is
with the processor pegged to zero waiting for network packets to make
the trip from England to Japan and back again, or for disks to spin,
or whatever.
And I haven't even talked about what happens if you want to compose
asynchronous operations further. Suppose you want to make
ArchiveDocuments an asynchronous operation that takes a delegate. Now
all the code that calls it has to be written in CPS as well. The taint
just spreads.
Getting asynchronous logic right is important, it’s only going to be
more important in the future, and the tools we have given you make you
“stand on your head and turn yourself inside out” as Professor Duggan
wisely said.
Continuation passing style is powerful, yes, but there's got to be a
better way of making good use of that power than the code above.
Entrambi gli articoli e le seguenti serie su una nuova funzione in linguaggio C # che muove tutto questo pasticcio nel compilatore e ti consente di scrivere il tuo codice come normale flusso di controllo con una parola chiave speciale per contrassegnare certe parti asincrone, vale la pena leggerlo anche se non sei uno sviluppatore C #. Non lo sono, ma è stata comunque un'esperienza illuminante quando l'ho incontrato per la prima volta.