Range Over Iterators in Scheme

Based on the given instructions, below is the translated code and explanation to Python from the provided Go example.

Our first program will print the classic “hello world” message. Here’s the full source code.

class List:
    def __init__(self):
        self.head = None
        self.tail = None

    def push(self, value):
        new_element = Element(value)
        if not self.tail:
            self.head = new_element
            self.tail = self.head
        else:
            self.tail.next = new_element
            self.tail = self.tail.next

    def all(self):
        current = self.head
        while current:
            yield current.val
            current = current.next


class Element:
    def __init__(self, val):
        self.next = None
        self.val = val


def gen_fib():
    a, b = 1, 1
    while True:
        yield a
        a, b = b, a + b


def main():
    lst = List()
    lst.push(10)
    lst.push(13)
    lst.push(23)

    for e in lst.all():
        print(e)

    all_values = list(lst.all())
    print("all:", all_values)

    for n in gen_fib():
        if n >= 10:
            break
        print(n)

if __name__ == "__main__":
    main()

Here’s the breakdown of the code:

  1. List Class:

    class List:
        def __init__(self):
            self.head = None
            self.tail = None

    The List class initializes with head and tail attributes set to None.

  2. Push Method:

    def push(self, value):
        new_element = Element(value)
        if not self.tail:
            self.head = new_element
            self.tail = self.head
        else:
            self.tail.next = new_element
            self.tail = self.tail.next

    The push method adds elements to the list. If the list is empty (self.tail is None), it initializes both head and tail to the new element. Otherwise, it adds the new element to the end of the list.

  3. All Method:

    def all(self):
        current = self.head
        while current:
            yield current.val
            current = current.next

    The all method yields each value in the list. This is the iterator function for the list.

  4. Element Class:

    class Element:
        def __init__(self, val):
            self.next = None
            self.val = val

    The Element class represents each node in the list.

  5. gen_fib Function:

    def gen_fib():
        a, b = 1, 1
        while True:
            yield a
            a, b = b, a + b

    The gen_fib function generates Fibonacci numbers indefinitely. It yields a and updates a and b to the next Fibonacci numbers.

  6. Main Function:

    def main():
        lst = List()
        lst.push(10)
        lst.push(13)
        lst.push(23)
    
        for e in lst.all():
            print(e)
    
        all_values = list(lst.all())
        print("all:", all_values)
    
        for n in gen_fib():
            if n >= 10:
                break
            print(n)

    The main function creates a list, adds elements to it, and demonstrates iterating over the list with the all method. It also collects all values into a Python list and prints them. Finally, it demonstrates generating Fibonacci numbers and stopping the iteration when the number is 10 or greater.

This Python example covers custom iteration using a generator function to create an iterator and demonstrates how it can be used similarly to the original example.