uncaught exception TopLevelCallcc

上のエントリに書いたcallccの例が、SML/NJでどうなるのか確かめようと思って試したら

Standard ML of New Jersey, Version 110.0.7, September 28, 2000 [CM; autoload enabled]
- fun mycallcc f = SMLofNJ.Cont.callcc (fn k => f (SMLofNJ.Cont.throw k)) ;
val mycallcc = fn : (('a -> 'b) -> 'a) -> 'a
- datatype r = R of (r -> r) | I of int ;
datatype r = I of int | R of r -> r
- val x = mycallcc (fn k1 => mycallcc (fn k2 => k1 (R k2))) ;
val x = R fn : r
- case x of R k => k (I 123) ;
stdIn:20.1-20.27 Warning: match nonexhaustive
          R k => ...
  

uncaught exception TopLevelCallcc
  raised at: build/compile.sml:378.30-378.44
- 

となった。SML/NJではトップレベルを跨ぐ継続は扱えないらしい

- val y = ref (fn x => x + 1) ;
val y = ref fn : (int -> int) ref
- mycallcc (fn k => (y := k; 123)) ;
val it = 123 : int
- !y 456 ;

uncaught exception TopLevelCallcc
  raised at: build/compile.sml:378.30-378.44
- 

なお、SML/NJのcallccは、Standard MLにはない独自拡張。また、(標準の)OCamlにはcallccはない。

追記:Leroyのcallccライブラリを利用した、OCamlでの実験。

# #load "callcc.cma" ;;
# let mycallcc f = Callcc.callcc (fun k -> f (Callcc.throw k)) ;;
val mycallcc : (('a -> 'b) -> 'a) -> 'a = <fun>
# type r = R of (r -> r) | I of int ;;
type r = R of (r -> r) | I of int
# let x = mycallcc (fun k1 -> mycallcc (fun k2 -> k1 (R k2))) ;;
val x : r = R <fun>
# match x with R k -> k (I 123) ;;
Characters 0-29:
Warning P: this pattern-matching is not exhaustive.
Here is an example of a value that is not matched:
I _
  match x with R k -> k (I 123) ;;
  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
val x : r = I 123
# 

callccとletだけでxの値がちゃんと(?)変わりました。