Implementation of iterator objects


iterator objects need to:
implement a predefined iterator interface and
store the current state of the iteration

Python has coroutines, so they do not need to explicitly maintain iteration state.
They can yield elements back to the main thread without terminating. Every time it yields something, it suspends itself until it's called again. Sort of like threads, but only one is active at any point. They switch control between each other.
def lexy(length):
    yield ''
    if length > 0:
        for ch in ['a','b','c','d']:
            for w in lexy(length - 1):
                yield ch + w

for w in lexy(3):
    print(w)

to get ‘aaa’: lexy(3) calls lexy(2) calls lexy(1) calls lexy(0)
these all suspend until their recursive call returns
when lexy(0) finishes, lexy(1) knows its inner loop is done and resumes. this repeats for the next iteration. All the coroutines are going back and forth resuming and suspending until the entire list is iterated over.
yield keyword suspends the function and sends the value back to the caller. function is not terminated.

Languages without iterators (such as C) can simulate iterators using function calls:
for (it = begin(coll); it != end(coll); it = next(it)){
    /* Do something with *it */
}



Goto



the CPU knows nothing of if/else, switch, loops, etc etc... it only has:
• number comparison and zero test,
• conditional/unconditional jumps (goto),
• “function” calls.
Compiler translates high level language constructs into these primitives.

Convenience vs control:
High level languages express complex logic with ease, but we have little control over what actually goes on in the CPU
Low level languages have tighter control over how the code runs. Used for performance-critical applications like systems programming, but more tedious for general purpose.
Some high-ish level languages (C, BASIC) include a GOTO instruction to jump to an arbitrary code location.
Combined with if statements we can express control flow like the CPU does.
...should we?

The use of GOTO is bad programming practice if the same effect can be achieved with a more highlevel construct. This is mostly because it makes code totally unreadable if you overuse it. (example: jump to label in another file, will work because of how C compiler works but makes no sense to reader)
Sometimes it is unavoidable. ex:
• break out of a loop
• break out of subroutine
• break out of deeply nested context


Subroutines



Claim: programming is all about building abstractions. We have some problem that we want to model with a computer, and we are abstracting aspects of that problem in order to program it.
Functions are the main method of building control abstractions.
The other form of abstraction is data abstractions.

A subroutine is a:


function if it returns a value
procedure if it does not and thus is called for its side effects

C only has functions, and even void functions kind of return something.
Other languages like Pascal, Modula, ADA, make a distinction between a function and a procedure. why?

Formal parameters of a subroutine: the ones that appear in the subroutine's declaration
int foo(int x, int y){}
Actual parameters of a subroutine: the values bound to the formal parameters when the subroutine is called.
foo(5, 3)

Activation record or stack frames:


in the 60's: (old versions of FORTRAN)
each functions arguments and local variables are stored in fixed regions of the programs memory space
does not support recursion
could never have two instances of “foo” running at the same time because it only has one chunk in the memory space.
modern languages:
each function call creates an activation record, or stack frame, on the program's call stack
supports recursion





Index