2012-08-22 7 views
2

나는 소수 생성하는 FP 스타일로 일부 이동 코드를 작성했습니다 :이 코드를 실행하면왜 코드가 실패합니까?

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) 
    } 

} 

, 그것은 느린 속도가 느린하게하고 결국 같은 런타임 오류 가져옵니다 여기

runtime: out of memory: [...] 

을 파이썬 코드의 버전이며, 그것은 잘 실행 :

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() 

나는 왜, 어떻게 그것을 해결하기 위해 궁금합니다. 내 코드 또는 golang 컴파일러의 문제입니까? 감사합니다.

추신 : 불쌍한 영어에 대한 죄송합니다.

답변

1

당신은

if p, ok := stream(); ok { 
     remaining := filter_stream(stream, func(q int) bool { return q % p != 0 }) 

그러나 모든 새로운 "p는"당신이 작성해야합니다에 대한 스트림

을 다시 새로운 " stream2는"

if p, ok := stream(); ok { 
     stream2 := .... 
     remaining := filter_stream(stream2, func(q int) bool { return q % p != 0 }) 
+0

stream2에 '....'을 입력 할 수 있습니까? – VonC

+0

http://play.golang.org/p/in9euT48_Z – Max

+0

아직도 이해가 가지 않습니다. http://play.golang.org/p/LDtWC36c9V 시도했지만 제대로 작동하지 않습니다. – VonC

2

문제는 재귀 당신의 체 기능입니다. 반복적으로 순환 체를 반복적으로 호출하여 스택을 불고 있다고 의심합니다.

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 
    } 
} 
관련 문제