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 scale_stream(stream, factor):
    return stream_map(lambda x: x * factor,
                      stream)
def merge(s1, s2):
    if is_none(s1):
        return s2
    elif is_none(s2):
        return s1
    else:
        s1head = head(s1)
        s2head = head(s2)
        return (pair(s1head, lambda: merge(stream_tail(s1), s2))
                if s1head < s2head
                else pair(s2head, lambda: merge(s1, stream_tail(s2)))
                if s1head > s2head
                else pair(s1head, lambda: merge(stream_tail(s1), stream_tail(s2))))
def integers_starting_from(n):
    return pair(n, lambda: integers_starting_from(n + 1))
S = pair(1, lambda: merge(scale_stream(S, 2),
                          merge(scale_stream(S, 3),
                                scale_stream(S, 5))))

print(eval_stream(S, 50))
