scheme - Weird thing happening with call/cc, Why? -
i simulated state-programming solution on lisp solve tree-flatten:
#lang racket (define (flat-tree-generator tr) (define initial? #t) (define state '()) (define (resume) (if (null? state) '() (let ((cont (car state))) (set! state (cdr state)) (cont)))) (define (recur tr) (cond ((null? tr) (resume)) ((not (pair? tr)) tr) (else (call/cc (lambda (k) (set! state (cons (lambda () (k (recur (cdr tr)))) state)) (recur (car tr))))))) (define (dispatch) (if initial? (begin (set! initial? #f) (recur tr)) (resume))) dispatch) (define g1 (flat-tree-generator '((0 (1 2)) (3 4)))) (define g2 (flat-tree-generator '(0 1 2 3 4)))
ok, if try:
(g1)(g2)(g1)(g2)(g1)(g2)(g1)(g2)(g1)(g2)
it work expected (output lines 0011223344). however, if try this:
(for ([e1 (in-producer g1 '())] [e2 (in-producer g2 '())]) (printf "e1: ~a e2: ~a\n" e1 e2))
you get:
e1: 0 e2: 0 e1: 0 e2: 1 e1: 0 e2: 2 e1: 0 e2: 3 e1: 0 e2: 4
or try:
(define (test) (g1)(g2)(g1)(g2)(g1)(g2)(g1)(g2)(g1)(g2)) (test)
you get:
'()
i confused.. why?
when call-with-current-continuation
in repl have guards between each statement while in test
end after first (g2)
after executing second unless tr
null. eg. execute second (g2)
, (g1)
in loop since end before code executed until hit (not (pair? tr))
g2
, g1
3 times emty list.
you don't need call/cc @ all. it's enough closures:
(define (flat-tree-generator tr) (define initial? #t) (define state '()) (define (resume) (if (null? state) '() (let ((cont (car state))) (set! state (cdr state)) (cont)))) (define (recur tr) (cond ((null? tr) (resume)) ((not (pair? tr)) tr) (else (set! state (cons (lambda () (recur (cdr tr))) state)) (recur (car tr))))) (define (dispatch) (if initial? (begin (set! initial? #f) (recur tr)) (resume))) dispatch)
or can use rackets generator features. code works in same manner:
(require racket/generator) (define (flat-tree-generator tr) (generator () (let rec ((tr tr)) (cond ((null? tr) tr) ((pair? (car tr)) (rec (car tr)) (rec (cdr tr))) (else (yield (car tr)) (rec (cdr tr)))))))
in both expected behaviour:
(for ([e1 (in-producer g1 '())] [e2 (in-producer g2 '())]) (printf "e1: ~a e2: ~a\n" e1 e2)) ; ==> void, side effect prints: e1: 0 e2: 0 e1: 1 e2: 1 e1: 2 e2: 2 e1: 3 e2: 3 e1: 4 e2: 4
Comments
Post a Comment