def stream_tail(stream):
    return tail(stream)()
def stream_ref(s, n):
    return (head(s)
            if n == 0
            else stream_ref(stream_tail(s), n - 1))

def stream_map(f, s):
    return (None
            if is_none(s)
            else pair(f(head(s)),
                      lambda: stream_map(f, stream_tail(s))))

def stream_for_each(fun, s):
    if is_none(s):
        return True
    else:
        fun(head(s))
        return stream_for_each(fun, stream_tail(s))
def stream_filter(pred, stream):
    return (None
            if is_none(stream)
            else pair(head(stream),
                      lambda: stream_filter(pred, stream_tail(stream)))
            if pred(head(stream))
            else stream_filter(pred, stream_tail(stream)))
def square(x): return x * x
def smallest_divisor(n):
    return find_divisor(n, 2)

def find_divisor(n, test_divisor):
    return (n if square(test_divisor) > n
            else test_divisor if divides(test_divisor, n)
            else find_divisor(n, test_divisor + 1))

def divides(a, b):
    return b % a == 0
def is_prime(n):
    return n == smallest_divisor(n)
def stream_enumerate_interval(low, high):
    return (None
            if low > high
            else pair(low,
                      lambda: stream_enumerate_interval(low + 1, high)))
def is_even(n):
    return n % 2 == 0
max_display = 9
def display_stream(s):
    def display_stream_iter(st, n):
        if is_none(st):
            pass
        elif n == 0:
            display("", "...")
        else:
            display(head(st))
            display_stream_iter(stream_tail(st), n - 1)
    display_stream_iter(s, max_display)
sum = 0

def accum(x):
    global sum
    sum = x + sum
    return sum

seq = stream_map(accum, stream_enumerate_interval(1, 20))

y = stream_filter(is_even, seq)

z = stream_filter(lambda x: x % 5 == 0, seq)

stream_ref(y, 7)

print(stream_ref(z, 3))

# expected: 305
