Annotation of researchv10no/cmd/sml/doc/callcc, revision 1.1.1.1

1.1       root        1: A set of new primitives has been added to ML to give access to continuations:
                      2: 
                      3: type 'a cont
                      4: val callcc : ('a cont -> 'a) -> 'a
                      5: val throw : 'a cont -> 'a -> 'b
                      6: 
                      7: The continuation of an expression is an abstraction of what the system
                      8: will do with the value of the expression. For example in the
                      9: expression:
                     10: 
                     11:                 if a orelse b then foo() else goo()
                     12: 
                     13: the continuation of the expression "a orelse b" can be described in
                     14: words as "if the value is true then compute foo() otherwise compute
                     15: goo()" and then continue in the context of the if-expression. Usually
                     16: the continuation of an expression is implicit, however, the primitive
                     17: callcc allows the programmer to capture and use these continuations.
                     18: 
                     19: The primitive callcc takes a function as an argument and applies it to
                     20: the current continuation.  The continuation of an expression of type 'a
                     21: has type 'a cont and is a first-class object. To capture the
                     22: continuation described above one would write:
                     23: 
                     24:    if callcc(fn k => a orelse b) then foo() else goo
                     25: 
                     26: Here the continuation of the callcc-application is captured by being
                     27: bound to k, but it is not used. Because the continuation is not used
                     28: the result is simply the result of the expression "a orelse b".  To
                     29: use the continuation a value must be supplied, and the computation
                     30: continues as if that value where the result of the callcc-application.
                     31: This is called throwing the continuation a value; it is performed by
                     32: applying "throw" to the continuation and the value.
                     33: 
                     34:  if callcc(fn k => (throw k false) orelse b) then foo() else goo()
                     35: 
                     36: Here, when the continuation k is thrown the value false, "orelse b" is simply
                     37: ignored, the callcc-application returns false, and goo() is then evaluated.
                     38: 
                     39: The type returned by a throw-expression is unconstrained like that of
                     40: a raise-expression and for the same reason:  neither of these
                     41: expressions ever return.
                     42: 
                     43: One of the less interesting uses of callcc is as an alternative to
                     44: exception handlers. For example:
                     45: 
                     46:     exception Prod
                     47: 
                     48:     fun prod l = let fun loop [] = 1
                     49:                       | loop(0::r) = raise Prod
                     50:                       | loop(a::r) = a * loop r
                     51:                 in loop l handle Prod => 0
                     52:                 end
                     53: 
                     54: can be written with callcc as follows:
                     55: 
                     56:     fun prod l = callcc(fn exit => 
                     57:                           let fun loop [] = 1
                     58:                                 | loop(0::r) = throw exit 0
                     59:                                 | loop(a::r) = a * loop r
                     60:                           in loop l
                     61:                           end)
                     62: 
                     63: But continuations are more general than exception handlers and can be
                     64: used to implement sophisticated control structures. These more complex
                     65: uses often involve subtle interactions with the type system.  For just
                     66: a taste of the techniques involved consider the following example
                     67: implementing an infinite loop.
                     68: 
                     69:     datatype State = S of State cont 
                     70:     fun state_throw (S k) = throw k
                     71: 
                     72:     let val s = callcc S
                     73:     in state_throw s s
                     74:     end
                     75: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.