7

I'm trying to solve the last exercise of this JavaScript Closure Tutorial which takes about Continuation Passing.

This is the exercise:

Define a function named bothC similar to seqC that takes functions fC and gC and continuations success and failure. The functions fC and gC both just take success and failure continuations. Your function bothC should call both fC and gC no matter what, but only call success if both succeeded, and failure otherwise. Don't forget, your function will never return!

This seems to be a valid answer:

var bothC = function (fC, gC, success, failure) {
    fC(
      function() {
        gC(success, failure);  
      },
      function() {
        gC(failure, failure);    
      }
    );
};

But why can't I just do this?

var bothC = function(fC, gC, success, failure) {
  fC(gC(success, failure), gC(failure, failure));
}
Bill the Lizard
  • 398,270
  • 210
  • 566
  • 880
helpermethod
  • 59,493
  • 71
  • 188
  • 276

3 Answers3

6

Any time you have a function followed by parens around an argument set (even if there are no arguments, that is still an arguments set), the message to JS is execute immediately. This means that gC(success, failure) actually runs gC and then returns whatever gC would return. fC(gC(success, failure), gC(failure, failure)); basically means, "call fC with the return of gC(success, failure) and gC(failure, failure) as parameters"

In order to prevent this action and still make it callable, you need to wrap it in a function(){} (it can be anonymous or not). That will make it into a returnable and callable object, instead of simply as a method call. fC(function() {gC(success, failure); }, function() { gC(failure, failure); } ); means, "call fC with a function which will call gC(success, failure) and a function which will call gC(failure, failure) as parameters"


Just as an FYI, the Sussman and Steele showed that continuations and closures, more or less, are the same thing, the difference is basically in syntax (this was in the late '70's. Read Gabriel/Steele History Of Lisp Pg. 33). JS has great closure syntax but, in my opinion, the best example of continuation in a currently popular language is the Python yield syntax. Just saying.

cwallenpoole
  • 79,954
  • 26
  • 128
  • 166
  • Disagree on python having the better syntax. If you have a yield statement in a python function, you can't refactor that to call other functions (deferring the call to yield). Once you have yield, that function is specially marked as a generator. This is important if you wish to maintain a system that relies on continuations (I wrote a simulator and really wanted to refactor my yield statements into two different functions). I'd love to see something with python's syntax adopt something as powerful as call/cc. Certainly something to think about when comparing to the JS syntax. – ccoakley Aug 08 '11 at 18:18
  • @ccoakley Well, I like that one because it is the clearest example of an actual continuation -- returning the function as something which can continue later, as opposed to a closure which returns a callable object. – cwallenpoole Aug 08 '11 at 20:35
  • Yeah, can't disagree there. You also allowed yourself an out with "best example ... in a current popular language." But just because nobody does it better doesn't mean I have to like it! Besides, I got used to the javascript syntax :) – ccoakley Aug 08 '11 at 20:37
  • Sigh... Yea... all too often we have [standards issues](http://xkcd.com/927/) like that... One day, the most beautiful language will be built that we can all agree is wonderful. (That day unfortunately [has passed and predates the modern computer](http://en.wikipedia.org/wiki/History_of_programming_languages)) – cwallenpoole Aug 08 '11 at 20:42
2

Because it calls gC (instead of defering it) and pass its result to fC.

Daniel A. White
  • 187,200
  • 47
  • 362
  • 445
2

You code won't work because it will immediately call gC twice when bothC is called. fC is supposed to take two continuations, meaning, they have to be callable functions, not the results of calling functions.

Ned Batchelder
  • 364,293
  • 75
  • 561
  • 662