類別 Continuation
Continuation
物件是由 Kernel#callcc
產生,在需要 continuation 之後。它們會保留一個回傳位址和執行緒環境,允許從程式中任何地方非本地回傳到 callcc
區塊的結尾。Continuations 有點類似於 C 的結構化版本 setjmp/longjmp
(儘管它們包含更多狀態,所以你可以將它們視為更接近執行緒)。
例如
require "continuation" arr = [ "Freddie", "Herbie", "Ron", "Max", "Ringo" ] callcc{|cc| $cc = cc} puts(message = arr.shift) $cc.call unless message =~ /Max/
產生
Freddie Herbie Ron Max
你也可以在其他方法中呼叫 callcc
require "continuation" def g arr = [ "Freddie", "Herbie", "Ron", "Max", "Ringo" ] cc = callcc { |cc| cc } puts arr.shift return cc, arr.size end def f c, size = g c.call(c) if size > 1 end f
這個(有點牽強)的範例允許內部迴圈提早放棄處理
require "continuation" callcc {|cont| for i in 0..4 print "#{i}: " for j in i*5...(i+1)*5 cont.call() if j == 17 printf "%3d", j end end } puts
產生
0: 0 1 2 3 4 1: 5 6 7 8 9 2: 10 11 12 13 14 3: 15 16
公開實例方法
cont[args, ...]
呼叫 continuation。程式會從 callcc
區塊的結尾繼續執行。如果沒有提供任何參數,原始 callcc
會回傳 nil
。如果提供一個參數,callcc
會回傳它。否則,會回傳包含 args 的陣列。
callcc {|cont| cont.call } #=> nil callcc {|cont| cont.call 1 } #=> 1 callcc {|cont| cont.call 1, 2, 3 } #=> [1, 2, 3]
別名為:call
call(args, ...) 按一下切換原始碼
cont[args, ...]
呼叫 continuation。程式會從 callcc
區塊的結尾繼續執行。如果沒有提供任何參數,原始 callcc
會回傳 nil
。如果提供一個參數,callcc
會回傳它。否則,會回傳包含 args 的陣列。
callcc {|cont| cont.call } #=> nil callcc {|cont| cont.call 1 } #=> 1 callcc {|cont| cont.call 1, 2, 3 } #=> [1, 2, 3]
static VALUE rb_cont_call(int argc, VALUE *argv, VALUE contval) { rb_context_t *cont = cont_ptr(contval); rb_thread_t *th = GET_THREAD(); if (cont_thread_value(cont) != th->self) { rb_raise(rb_eRuntimeError, "continuation called across threads"); } if (cont->saved_ec.fiber_ptr) { if (th->ec->fiber_ptr != cont->saved_ec.fiber_ptr) { rb_raise(rb_eRuntimeError, "continuation called across fiber"); } } rollback_ensure_stack(contval, th->ec->ensure_list, cont->ensure_array); cont->argc = argc; cont->value = make_passing_arg(argc, argv); cont_restore_0(cont, &contval); UNREACHABLE_RETURN(Qnil); }
也別名為:[]