diff --git a/ch_1_intro.md b/ch_1_intro.md index ecdb69d..207993e 100644 --- a/ch_1_intro.md +++ b/ch_1_intro.md @@ -120,7 +120,6 @@ Get a lot of it. Be careful using this glue, though; it is very flammable. Don't smoke and glue at the same time. - ### Dialects Unfortunately, there is not just one Logo. While some Logos are more alike than others, most have quirks. @@ -196,7 +195,7 @@ Review the turtle reference commands: `FD`, `BK`, `PU`, `PD`, `RT` `LT`. In the cartesian system, the destination is the important thing; in the turtle reference system, it's the trip. ### Making shapes -Let's draw a simpel shape using turtle reference commands. +Let's draw a simple shape using turtle reference commands. Suppose you would like the turtle to draw a square box located at the center of the screen (usually the origin of the coordinate system). Here are the steps you would take: @@ -216,10 +215,10 @@ That's it. The turtle has walked around the four sides of a size 50 box, arriving back to where it started. These prose commands would translate into Logo as: -1. `FD 50 RT 90` -2. `FD 50 RT 90` -3. `FD 50 RT 90` -4. `FD 50 RT 90` +1. `forward! (50); right! (0.25)` +2. `forward! (50); right! (0.25)` +3. `forward! (50); right! (0.25)` +4. `forward! (50); right! (0.25)` The third and last step would be to type these commands on the keyboard. And here is what you will see. @@ -234,11 +233,13 @@ Review the `REPEAT` command; it is exactly what we need here. Try it. ``` -CG -REPEAT 4 [FD 50 RT 90] +repeat 4 { + forward! (50) + right! (0.25) +} ``` -Notice that the line `REPEAT 4 [FD 50 RT 90]` is a kind of operational definition of what a square is: a square is four sides, four `FD` commands, with each side joined at right angles to the next, the `RT 90` commands. +Notice that the line `repeat 4 { forward! (50); right! (0.25) }` is a kind of operational definition of what a square is: a square is four sides, four `FD` commands, with each side joined at right angles to the next, the `RT 90` commands. That's tidy, but it's still a bore to type two lines each time you want a size 50 box on the screen. After all, you may want to draw 100 boxes. @@ -257,9 +258,12 @@ Let's get on with writing the necessary procedure. Here it is: ``` -TO BOX50 - REPEAT 4 [FD 50 RT 90] -END +fn box50! () -> { + repeat 4 { + forward! (50) + right! (0.25) + } +} ``` Logo will add `BOX50` to all its other commands. @@ -276,7 +280,14 @@ Keep track of what you are doing in your notebook so that you can reconstruct yo Here is a simple command that wraps boxes around the screen: ``` -REPEAT 25 [PD BOX50 PU RT 15 FD 60 LT 15] +repeat 25 { + pendown! () + box50! () + penup! () + right! (inv (24)) + forward! (60) + left! (inv (24)) +} ``` ### Wrapped boxes @@ -314,9 +325,12 @@ You can now draw boxes of any size from, say, 1 unit to 5000 units. Use this example as a "pattern" for incorporating an argument into a procedure. ``` -TO BOX :EDGE - REPEAT 4 [FD :EDGE RT 90] -END +fn box! (edge) -> { + repeat 4 { + forward! (edge) + right! (0.25) + } +} ``` ### Putting a demonsuation procedure together @@ -339,13 +353,22 @@ If you wish to show off with several designs, you could design specific Logo pro Here is an example of such a demonstration procedure: ``` -TO DEMO - ; A demonstration procedure to show off a design - ; produced from multiple boxes of different sizes. - REPEAT 4 [BOX 100 BOX 98 BOX 96 BOX 75 BOX 40 - BOX 35 BOX 30 RT 90] -END +& A demonstration procedure to show off a design +& produced from multiple boxes of different sizes. +fn demo () -> { + repeat 4 { + box! (100) + box! (98) + box! (96) + box! (75) + box! (40) + box! (35) + box! (30) + right! (0.25) + } +} ``` + To see the pattern defined by `DEMO`, type it: {{Figure 4: Differently sized boxes. Top of p. 15.}} @@ -399,9 +422,12 @@ Why not call the generalized procedure `NGON` for n-sided polygon? Look again at the procedure BOX and decide what needs to be changed to turn `BOX` into `NGON`. ``` -TO BOX :EDGE - REPEAT4 [FD :EDGE RT 90] -END +fn box! (edge) -> { + repeat 4 { + forward! (edge) + right! (0.25) + } +} ``` You need to add a second argument `:N`. @@ -423,13 +449,16 @@ Review the Logo notation to add, subtract, multiply, and divide.) You are ready to write the new procedure NGON: ``` -TO NGON :N :EDGE - REPEAT :N [FD :EDGE RT 360/:N] -END +fn ngon! (n, edge) -> { + repeat n { + forward! (edge) + right! (inv (n)) + } +} ``` Try it out. -Notice that when: N becomes large, the drawn figure becomes a circle (almost). +Notice that when `:N` becomes large, the drawn figure becomes a circle (almost). Carry out some clever visual experiments with `NGON`s. ### Some observations @@ -481,12 +510,12 @@ For a 90% shrinkage I would use `:GROWTH`=.9." ### A procedure to spin polygons ``` -TO SPINGON :N :EDGE :ANGLE :GROWTH - NGON :N :EDGE - RT :ANGLE - SPINGON :N (:EDGE*:GROWTH) :ANGLE :GROWTH - ; Here is the recursion. -END +fn spingon! (n, edge, angle, growth) -> { + ngon! (n, edge) + right! (angle) + spingon! (n, mult (edge, growth), angle, growth) + & Here is the recursion +} ``` What is new here? @@ -501,14 +530,17 @@ Will `SPINGON` ever stop? Try it out. ### Some spingons ``` -SPINGON 30 2 10 1.02 95 +spingon! (30, 2, inv (36), 1.02, 95) ``` {{Figure 7: Snail-ish spingon. Top of p. 21.}} ``` -HOME CG REPEAT 3 [SPINGON 4 120 0 .95 50 RT 90] -SPINGON 4 120 0 .95 19 +repeat! 3 { + spingon! (4, 120, 0, 0.95, 50) + right! (0.25) +} +spingon! (40, 120, 0, 0.25, 19) ``` {{Figure 8: Frame-ish spingons. Bottom of p. 21.}} @@ -524,15 +556,17 @@ Review the conditional commands in Logo. Using the `IF` phrase, everything becomes very tidy. ``` -TO SPINGON :N :EDGE :ANGLE :GROWTH :TIMES - ; Note the new argument above. - IF :TIMES < 1 [STOP] - ; This is the conditional stopper. - NGON :N :EDGE - RT :ANGLE - SPINGON :N (:EDGE*:GROWTH) :ANGLE :GROWTH (:TIMES-1) - ; Note the new argument above. -END +fn spingon! (n, edge, angle, growth, times) -> { +& Note the new argument above. + if lt? (times, 1) then :stop + & This is the conditional stopper. + else { + ngon! (n, edge) + rt! (angle) + spingon! (n, mult (edge, growth), angle, growth, dec (times)) + & Note the new argument above. + } +} ``` ### Boring logistics @@ -560,15 +594,17 @@ Here is an example from this chapter. Notice the use of comments, too. ``` -TO SPINGON :N :EDGE :ANGLE :GROWTH :TIMES - ; Note the new argument above. - IF :TIMES < 1 [STOP] - ; This is the conditional stopper. - NGON :N :EDGE - RT: ANGLE - SPINGON :N (:EDGE*:GROWTH) :ANGLE :GROWTH (:TIMES-1) - ; Note the new argument above. -END +fn spingon! (n, edge, angle, growth, times) -> { +& Note the new argument above. + if lt? (times, 1) then :stop + & This is the conditional stopper. + else { + ngon! (n, edge) + rt! (angle) + spingon! (n, mult (edge, growht), angle, growht, dec (times)) + & Note the new argument above. + } +} ``` Third, the _body structuring_ rule. @@ -579,13 +615,15 @@ Here is an example. Notice that the Logo material within the [repeat brackets] would have been difficult to read if the long statement had not been divided into several short lines. ``` -TO SQUIGGLE :A :B :N - REPEAT :N [ FD :A - - RT 130 - - FD :A - - RT 50 - - BK :B ] -END +fn squiggle! (a, b, n) -> { + repeat n { + forward! (a) + rightt! (inv (3)) + forward! (a) + right! (inv (6)) + back! (b) + } +} ``` The symbol "`-`" indicates, of course, that the return key should not be used becausethe Logo statement continues. @@ -614,7 +652,7 @@ This is another way to ask yourself what information must be given to `CNGON` so That means that the first line of the new procedure will look like this: ``` -CNGON :N :RAD +cngon! (n, rad) ``` Second, imagine yourself as the turtle. @@ -689,14 +727,19 @@ No more words are necessary. Here it is. ``` -TO CNGON :N :RAD - PU FD :RAD - RT (angle) PD - NGON :N (edge) - LT (angle) - PU BK :RAD PD -END +fn cngon! (n, rad) -> { + penup! () + forward! (rad) + right! (::angle::) + pendown! () + ngon! (n, ::edge::) + left! (::angle::) + penup! () + back! (rad) + pendown! () +} ``` + The procedure is sketched. And we know what we know and what we don't. The two amounts, (angle) and (edge), are still unknown. @@ -719,31 +762,31 @@ The external angle is the turning angle used in `NGON`. What about the internal angles, labeled b. We need some work here: -(1) c = 360/n, +(1) c = 1/n, -(2) c + b = 180. +(2) c + b = 1/2. Putting these two equations together and solving for b gives -(3) b=180*(n-2)/n. +(3) b = 1/2 - 1/n. We are now ready to handle the first problem: Find d in terms of n. -(4) d + b/2 = 180. +(4) d + b/2 = 1/2. Putting (3) and (4) together and solving for d gives -(5) d = 180 - 90*(n-2)/n <---**First problem solved**. +(5) d = 1/4 + 1/2n <---**First problem solved**. OK, now look at the second problem: Find e in terms of R and n. (6) sin (a/2) = (e/2)/R, -(7) a = 360/n. +(7) a = 1/n. Putting (7) and (6) togetherand solving for e gives -(8) e = 2\*R\*sin(180/n) <---**Second problem solved**. +(8) e = 2\*R\*sin(1/2n) <---**Second problem solved**. Review the following trig functions: sine, cosine, and tangent. What is ani arctangent? @@ -754,34 +797,45 @@ Glue them on the inside cover of your notebook. Here's how far we have gotten with `CNGON`: ``` -TO CNGON :N :RAD - PU FD:RAD - RT (angle) PD - NGON :N (edge) - LT (angle) - PU BK :RAD PD -END +fn cngon! (n, rad) -> { + penup! () + forward! (rad) + right! (::angle::) + pendown! () + ngon! (n, ::edge::) + left! (::angle::) + penup! () + back! (rad) + pendown! () +} ``` Now we can replace `(angle)` and `(edge)` with the needed expressions. Here is the finished `CNGON`: ``` -TO CNGON :N :RAD - PU FD :RAD - RT 180 - (90*(:N-2)/:N) PD - NGON :N (2*:RAD*SIN (180/:N)) - LT 180 - (90*(:N-2)/:N) - PU BK :RAD PD -END +fn cngon! (n, rad) -> { + let angle = sub (inv (2), inv (n)) + let edge = mult (2, rad, sin (inv (mult (2, n)))) + + penup! () + forward! (rad) + right! (angle) + pendown! () + ngon! (n, edge) + left! (angle) + penup! () + back! (rad) + pendown! () +} ``` ### Lessons and tips -When solving visual problems, like this CNGON thing, try to break the single big problem down into several smaller problems. +When solving visual problems, like this `CNGON` thing, try to break the single big problem down into several smaller problems. Solve each of the small problems in turn, and then plug the little solutions together to form one big solution. #### Exercise 1.2 -Put together one or more DEMO procedures that make imaginative use of the ideas presented and reviewed in this chapter. +Put together one or more `DEMO` procedures that make imaginative use of the ideas presented and reviewed in this chapter. Modify every procedure in the chapter. Make them act more strangely. @@ -825,3 +879,26 @@ Don't forget the following tricks: research. 6. Translate the words into Logo commands. 7. Test it out with realistic and totally outlandish argument values + +### Notes for adaptation +* Don't use abbreviations everywhere! +* Stopping recursion looks different. + - This will be different once we get actors and Ludus runs in a different thread. Is this a prerequisite? +* Math is harder, since we don't have familiar arithmetic operators. +* A few places there are arbitrary degrees; figure out how to make this friendlier. + - Throughout, replace degrees with turns. +* Consider a helper function, `double`, to simplify the math for `cngon!`. +* Procedure -> function, throughout. +* The canvas doesn't (currently) wrap, so the example of many squares with wrapping needs to be a bit different. +* Prepping the annotated SVGs will be a thing. + - Do we want hand-drawn stuff? Consider using the iPad. +* This we do not need here: + - Appeals to a manual + - The `-` character to continue a line +* Things we do need that are absent (in no particular order): + - `let` bindings + - M-expression math + - A discussion of turns instead of degrees + - A discussion of empty parens/function calls + - A discussion of bangs in names + - A discussion of question marks in names