Why does this go code fail?
Question: I have written some go code in FP style to generate primes:

    
    
    package main
    import (
        "fmt"
    )
    
    func gen_number_stream() func() (int, bool) {
        i := 1
        return func() (int, bool) {
            i += 1
            return i, true
        }
    }
    
    func filter_stream(stream func() (int, bool), f func(int) bool) func() (int, bool) {
        return func() (int, bool) {
            for i, ok := stream(); ok; i, ok = stream() {
                if f(i) {
                    return i, true
                }
            }
        return 0, false
        }
    }
    
    func sieve(stream func() (int, bool)) func() (int, bool) {
        return func() (int, bool) {
            if p, ok := stream(); ok {
                remaining := filter_stream(stream, func(q int) bool { return q % p != 0 })
                stream = sieve(remaining)
                return p, true
            }
            return 0, false
        }
    }
    
    
    func take(stream func() (int, bool), n int) func() (int, bool) {
        return func() (int, bool) {
            if n > 0 {
                n -= 1
                return stream()
            }
            return 0, false
        }
    }
    
    func main() {
    
        primes := take(sieve(gen_number_stream()), 50)
    
        for i, ok := primes(); ok; i, ok = primes() {
            fmt.Println(i)
        }
    
    }
    

when I run this code, it becomes slower and slower and finally gets a runtime
error like this:

    
    
    runtime: out of memory:  [...]
    

here is a version of python code, and it just runs fine:

    
    
    def gen_numbers():
        i = 2
        while True:
            yield i
            i += 1
    
    def sieve(stream):
        p =  stream.next()
        yield p
        for i in sieve( i for i in stream if i % p != 0 ):
            yield i
    
    def take(stream,n):
        for i,s in enumerate(stream):
            if i == 50: break
            yield s
    
    def main():
        for i in take(sieve(gen_numbers()),50):
            print i
    
    
    if __name__ == '__main__':
        main()
    

I wonder why and how to fix it. Is it a problem of my code or golang compiler?
Thanks!

PS: Sorry for my poor english.


Answer: The problem is your sieve function which is recursive. I suspect that you are
blowing your stack by continually calling sieve recursively in a loop.

    
    
    func sieve(stream func() (int, bool)) func() (int, bool) {
        return func() (int, bool) {
            if p, ok := stream(); ok {
                remaining := filter_stream(stream, func(q int) bool { return q % p != 0 })
                stream = sieve(remaining) // just keeps calling sieve recursively which eventually blows your stack.
                return p, true
            }
            return 0, false
        }
    }
    

