When circumstances allow, I'll be typing up bits of my lecture notes and posting them online. These may or may not bear any resemblance to the actual lectures.
0 5 10 15 20 25
Here's a sample procedure which takes a name as input and outputs the initials in the name:
to initials.recursive :name ifelse (emptyp :name)~ [output ]~ [output sentence (first (first :name)) (initials.recursive butfirst :name)] endWhat is the stop condition? Where is the recursive call? Must the stop condition be checked before the recursive call?
When making the recursive call, we assume that initials.recursive can successfully output "the rest of the list" of initials. This is the "leap of faith" the author mentions.
The procedure outputs  when it reaches its stop condition, and longer and longer lists as it outputs the initials from different stages of "the rest of the list". This is typical of recursion. Our factorial procedure behaved similary, outputting 1 as its stop condition and larger and larger products as the program ran to completion.
to factorial :number if equalp :number 0 [output 1] output :number * factorial (:number - 1) end(What is the stop condition? Where is the recursive call?)
Can you write a recursive procedure which accepts a positive integer n as input and outputs the sum of the odd integers up to n? What about a maze game procedure that ends after the player makes a total of three lefts or one right, assuming that lefts and rights cancel? (The player wins as soon as he or she is facing in the correct direction.)
local "score make "score 0 make "score sum :score 1(Of course, the instruction to make "score sum :score 1 was inside the list of instructions to be followed if the user got the correct answer.)
This is typical of programs by authors who prefer using make to thinking about functional programming techniques. Here is our initials procedure again, using for instead of recursion.
to initials.for :name local "initiallist make "initiallist  ; This is called initializing. No pun intended. for [i 1 [count :name]] ~ [make "initiallist sentence :initiallist first item :i :name] ; The list of instructions above adds the ith initial to the list. output :initiallist endNote that here we use item and make, where our functional programming (recursive) examples instead use butfirst and a "leap of faith" involving output. Also note that count :name is enclosed in brackets to force Logo to evaluate this instruction and get the target number.
There are two steps needed to accumulate values in a variable in this way:
local "varname make "varname 0
make "varname :varname + :numberHere's a procedure which calculates factorials using for:
to factorial.for :num local "fac make "fac 1 for [i 1 :num] [make "fac :fac * :i] output :fac endWhy did we make "fac 1 and not 0 in this procedure? Where does the initialization happen? Where do we add on to the value stored in the variable?
Can you write a procedure which uses for to find the sum of the odd numbers from 1 to n? If so, can you write a procedure to find the sum of the first k odd numbers?
Can you write a procedure which uses for and accepts a list as input then prints each item in the list? Which outputs the list in reverse?
The hardest part of the problem is the leap of faith. Suppose we already had a procedure that could draw a small collection of nested squares. How would we write a procedure to add one square to that collection?
What information do we need? We need the size of the new square that we're drawing, the size of the collection of squares to be drawn inside that square, and information on where to position the smaller collection of squares inside the large outer square.
We can make the size of the square we're drawing an input to our recursive procedure:
to squareview :size ; ; ; ; endThe size of the collection of squares inside the starter square will depend on the size of the starting square. After some thought, you may notice a 45-45-90 triangle at the corner of each square. If the two legs of that triangle have length :size/2, the Pythagorean theorem says that the hypotenuse must have length :size/sqrt(2).
to square :size repeat 4 [forward :size right 90] end to squareview :size square :size ; ; squareview :size / (sqrt 2) endOur procedure isn't done yet. What are we missing?
The size of the squares is dictated by the variable size, so we just stop when the squares get small enough.
to squareview :size square :size if lessp :size 2 [stop] ; squareview :size / (sqrt 2) end(What happens if we mistakenly say if lessp 2 :size? Why don't we need an output command as we did with the factorial program?)
First, figure out where your turtle will be when it finishes drawing the outside square. Then figure out where it needs to move to to draw the next square.
In this example, the turtle needs to move forward :size/2 distance, then turn to the right by 45° before starting the inside square.
to squareview :size square :size if lessp :size 2 [stop] forward :size/2 right 45 squareview :size / (sqrt 2) end