How to implement Python-style generator in Scheme (Racket or ChezScheme)?

前端 未结 4 1396
终归单人心
终归单人心 2021-01-03 07:46

today I solve the N-queen problem using Scheme but it is extremely slow compared to the same version of Python. when N = 8, Scheme takes 90+ seconds! I know one reason is th

4条回答
  •  小鲜肉
    小鲜肉 (楼主)
    2021-01-03 08:32

    Using continuations for this case (as suggested in the link) is unjustified. Here's a simpler idea: let's define our generator as a thunk (a no-args function) that stores as part of its environment the starting point, the maximum allowed value, the increment and the current element. Every time we call the procedure, the current element will be updated. The following code behaves similar to Python 3.x range() function (or Python 2.x xrange()):

    (define (generator start stop step)
      (let ((current (- start 1)))
        (lambda ()
          (cond ((>= current stop) #f)
                (else
                 (set! current (+ current step))
                 current)))))
    

    Now the next procedure will simply call the generator until the maximum value is reached, at this point the generator will start returning #f for each subsequent call:

    (define (next generator)
      (generator))
    

    For example:

    (define g (generator 0 3 1))
    (next g) ; 0
    (next g) ; 1
    (next g) ; 2
    (next g) ; 3
    (next g) ; #f
    

    Another alternative would be to use streams, but I'll stick with the above solution, it's simple enough and should work on any Scheme interpreter. And yet another alternative - if you're coding in Racket, just use a sequence (which is also a stream), like this:

    (for ([i (in-range 0 4 1)])
      (display i))
    
    => 0123
    

提交回复
热议问题