Today: if statement, ==, function call, decomposition

go-green While Loop Example

Recall from last time, go-green demo:

> go-green

One Code - Many Cases - Generality

While Loop - Zero Iterations

Aside: Bit Controls


If Statement - Logic

While loop is power. If-statement is control, controlling if lines are run or not

Problem statement: Move bit forward until blocked. For each moved-to square, if the square is blue, change it to green. (Demo: this code is complete.).

> If Demo

For reference here is the code:

def if_demo(filename):
    bit = Bit(filename)
    while bit.front_clear():
        bit.move()
        if bit.get_color() == 'blue':
            bit.paint('green')

If Statement Syntax

Syntax 4 parts (similar to "while"): if, boolean test-expression, colon, indented body lines

if test-expr:
    body lines

If Statement Operation

Look At Test Expression

Here are the key lines of code:

    ....
    if bit.get_color() == 'blue':
        bit.paint('green')
    ....

1. bit.get_color() Expression

Suppose bit is on a squared painted 'blue'. Here is diagram - visualizing that bit.get_color() is called and it returns the value'blue' to be used by the calling code.

alt: get_color() returns the value 'blue'

2. == Compares Two Values - Boolean

if bit.get_color() == 'red':
    # run this if color is 'red'

if bit.get_color() == None:
    # run this if square is not painted

if bit.get_color() != 'red':
    # run this if square is anything but 'red'
    # e.g. 'green' 'blue' or None

Decomposition - Program and Functions

"Divide and Conquer" - a classic strategy, works great with code

Functions - Wizard of EarthSea

In with Wizard of EarthSea novels by Ursula Le Guin .. each thing in the world has its true name. A magician calls a thing's true name, invoking that thing's power. Function calls work like this - a function has a name, you invoke the function by its name, getting its power.

How To Call a Function

We've seen def many times - defines a function. Note that each function has a name and body lines of code, like this "go_west" function:

def go_west(bit):
    bit.left()
    bit.paint('blue')
    ...

1. Call by noun.verb

To "call" a function means to go run its code. One way to call a function in Python is the "object oriented" form, aka noun.verb. The bit functions look like that, e.g. bit.left(), here "left" is the name of the function.

2. Call by name

The other way to call a function is just by using its name with parenthesis. For the above function named "go_west", code to call it looks like:

    ...
    go_west(bit)
    ...

Both of these function-call styles are widely used in Python code.

What Does Function Call Do?

Say the program is running through some lines, which we'll call the "caller" lines. Then the run gets to the following function call line; what happens?

    # caller lines
    bit = Bit('5x5.world')
    go_west(bit)
    bit.left()
    ...

What this means simply is: (a) go run the lines inside the "go_west" function, suspend running here in the caller. (b) When go_west() is done, return to these caller lines and continue running with the next line. In other words, the program runs one function at a time, and function-call jumps over to run that function.


Fill World Blue Example

The whole program does this: bit starts at the upper left facing down. We want to fill the whole world with blue, like this

Program Before:
world without blue, bit at upper left

Program After:
world filled blue, bit at lower left

> Fill

1. - Decompose fill_row_blue() "helper" function

First we'll decompose out a fill_row_blue() function that just does 1 row. Work on that function first.

This is a "helper" function - solves a smaller sub-problem.

fill_row_blue() Before (pre)
bit at left facing south

fill_row_blue After (post):
row filled with blue, bit back at start position

Function Pre/Post Conditions

Pre/Post - Why Do I Care?

Look at fill_row_blue() Function

def fill_row_blue(bit):
    bit.left()
    bit.paint('blue')
    while bit.front_clear():
        bit.move()
        bit.paint('blue')
    bit.right()
    bit.right()
    while bit.front_clear():
        bit.move()
    bit.left()

Run fill_row_blue()

2. Write fill_world_blue()

fill_world_blue() Functions - A Great Deal!


More Bit Tests: bit.left_clear() + not

if bit.left_clear():
    # run here if left is clear

if not bit.left_clear():
    # run here if left is blocked, aka not-clear

Decomposition Example / Exercise: Cover

Bit starts next to a block of solid squares (these are not "clear" for moving). Bit goes around the 4 sides clockwise, painting everything green.

Cover Before (pre):
world without blue cover done

cover_row() After (post):
alt: after one cover_side

cover_square() After (post):
world filled blue done

1. Run cover_side()

cover_row(bit): Move bit forward until the right side is clear. Color every square green. (demonstrates not left-clear test).

Run this code with case-1, see what it does. Study the code to see how it works, think about its pre/post (make a little drawing).

2. Work on cover_square()

cover_square(bit): Bit begins atop the upper left corner, facing right. Paint all 4 sides green. End to the left of the original position, facing up.

Start by calling cover_row() once. How can we solve the whole thing? How to address the pre/post conditions of cover_side()? Key ideas:


Optional - Probably Not Getting This Far

Boolean Expressions: and or not

Boolean Examples..

Q1: when is the following if-test True?

    if bit.left_clear() and bit.right_clear():
        # when does this happen?

Q2: when is the following if-test True? (just changing and to or)?

    if bit.left_clear() or bit.right_clear():
        # when does this happen?

Q3: when is the following if-test True?

    if not bit.left_clear():
        # when does this happen?

Answers.. A1: When either both left and right are clear A2: When either left or right are clear (or both) A3: When the left is blocked (i.e. lear_clear() returns False)

Put It All Together - Applied Boolean Code

> Bit Logic1 Exercises

First 3 are demos - walk through them

Then last 3 are little exercises to try .. see how many we get through today


Infinite Loops

Nick demo:

while bit.front_clear():
    bit.left()
    bit.right()

Here's a more subtle bug. What is the problem here?

while bit.front_clear():
    bit.move

A: Easy typo to make - without parenthesis, the move function does not happen! Correct is bit.move()