HN2new | past | comments | ask | show | jobs | submitlogin

Awesome explanation from first principles.

One thing that catches me all the time is that when writing examples in a functional language, the continuation of call/cc is on the left of the call to call/cc.

Rewriting your example as imperative statements might be more understandable to non-functional[1] programmers like me:

   x = call/cc ...
   print x ;; <- this is the continuation
Of course this does not work well with your nice reduction based explanation, but can be made to work if you go for a CPS transformation based explanation.

[1] pun fully intended:



For sure! Like I said, this is very similar to fork(), and you've basically called out why :)

    pid = fork();
    if (pid != 0) {
      printf("parent!");
    } else {
      printf("child!");
    }
    // Displays, in principle, though in any order:
    //   parent!
    //   child!
`fork` captures "the rest of the program" -- the part after the `;` on `fork()`, although confusingly including the `which = _` -- and causes it to be run twice, each with a different return value (which really means "passed to the continuation").

> the continuation of call/cc is on the left of the call to call/cc.

Kiiind of. It's really around the call to call/cc -- the "101" and "5" in this example are to the right, while the "+" is to the left:

      (+ (call/cc (\k. k 42)) 101 5)
    = (\k. k 42) (\x. (+ x 101 5))
    = (\x. (+ x 101 5)) 42
    = (+ 42 101 5)
In terms of a syntax tree, the continuation is above the call to call/cc. The left/right distinction only really shows for super-simple examples. But, conversely, the argument for function application is always below the application sense, so there's a very reliable duality here.

(Another, slightly twisted perspective is that a syntax tree is, after all, a graph; and following the parent of a node leads to a subgraph just as well as following a child. The fact that this subgraph is "upside-down" is just an extra detail ;), but you can use this subgraph during reduction just like you would a child subgraph. In this way, call/cc is literally just function application, but applying the parent subgraph instead of a normal child.)

((There's a third, incredibly boring member of this family... we can pass one child to another with `apply`, and pass the context to a child with `call/cc`. What lets us pass a child to the context? `id`, or the no-op operator!))




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: