Skip to content
September 27, 2011 / cdsmith

Haskell For Kids: Week 6

(This is from last week.  Yes, I’m really late in posting this… sorry!  This week’s summary will be up in a couple days.)

Practice Time

Welcome to the week 6 summary of Haskell for Kids, my middle school level (that is, ages 12 – 13 ish) programming class using Haskell and Gloss at the Little School on Vermijo.  You can go back and review weeks 1, 2, 3, 4, and 5 if you like.

This week was time for practice.  Instead of introducing any new ideas, I’ll just post the practice activity we did together in class on Tuesday.  The way we practiced was very simple: I drew pictures, and we tried to write descriptions of those pictures.  Rather than waste time, let’s just jump right into it.  It might help to download (and maybe print out) the PDF file from the end of week 5 (follow the link earlier) for a reminder of how to write list comprehensions.

I’m not including answers, because it’s too easy to just read ahead!  If you can’t figure one of them out, feel free to ask for help in the comments.

Practice 1

Hints: None!  Hopefully this one is easy.

Practice 2

Hints: The parameter to circle is a number.  Use the variable from the list comprehension for that.

Practice 3

Hints: This one should also be easy.  It’s just a stepping stone to the next practice.

Practice 4

Hint: The list comprehension variable tells you how far to translate.

Practice 5

Hint: Don’t do this with rotate.  You can change just one thing from practice 4 and make this work.  Remember that you can use the list comprehension variable more than once.

Practice 6

Hint: Remember that if you translate something first and then rotate it, it will be rotated around the middle of the picture.

Practice 7

Hint: Here you’ll want to use two variables in your list comprehension.  One of the examples from the reference page shows you how to do this.

Practice 8

Hint: Again you want two variables, but this time one of them will be used in translate and the other one in rotate.

Projects

In addition to this, we just worked on our list comprehension projects.  If you remember from last week, the project was to pick something repetitive and draw it.  I suggested a U.S. flag if you’re in the U.S. and don’t have another idea.  Some of the other projects kids from our class came up with were an iPhone with a grid of icons, a keyboard (the musical type!), and a galaxy with spiral arms and a background of stars.  So be creative!

Oh, and I have to show off Sophia’s keyboard, because she worked really, really hard on it, and I’m very impressed.  It’s a great use of list comprehensions, too.  Here goes…

September 14, 2011 / cdsmith

Haskell for Kids: Week 5

Functions and Variables!

Welcome to the week 5 summary of my Haskell class for kids.  You can go back and read the previous weeks summaries, if you like:

  1. First Week: The Basics
  2. Second Week: Organization
  3. Third Week: Playing Computer
  4. Fourth Week: Top Down Design

Our theme this week will be functions and variables.

Section 1: How to Draw an Awesome Elephant

We started with a simple example.  We already know how to draw a star:

star = polygon [
    ( -75, -100),
    (   0,   87),
    (  75, -100),
    (-100,   25),
    ( 100,   25),
    ( -75, -100)
    ]

and Sophia has figured out how to draw an elephant (this is one of her early versions, actually, but I picked it because it’s shorter; you don’t need to understand it):

elephant = pictures [
      rotate (-20) (scale 3 2 (translate 30 40 (circleSolid 25))),
      translate 150 (-20) (rectangleSolid 40 80),
      translate (-10) 40 (scale 1.5 1 (circleSolid 80)),
      translate 50 (-50)(rectangleSolid 40 70),
      translate (-60) (-50) (rectangleSolid 40 70),
      translate (-140) 50 (rotate 100 (rectangleSolid 10 40))
      ]

But now we want to draw a really awesome star.  Being “awesome”, of course, means being twice as large, and the color chartreuse.

awesomeStar     = scale 2 2 (color chartreuse star)
awesomeElephant = scale 2 2 (color chartreuse elephant)

and

But, by now, you can probably guess that I can draw an awesome version of any picture.  There are awesome spaceships, awesome shoes, awesome bicycles… give me any picture at all, and I can tell you how to draw an awesome one: you draw it twice as big, and make it chartreuse.  It will get tiresome to keep repeating ourselves, but luckily, Haskell lets us say this just once:

awesome x = scale 2 2 (color chartreuse x)

Now we don’t need to define a bunch of variables like awesomeStar and awesomeElephant.  Instead, we can just write awesome star, with a space in between the two!

We’ve seen things like this before: awesome is called a function, and the thing that we’re making awesome is called its argument.  But up until now, we’d only used functions that other people gave us… like rotate and translate in the Gloss library.  Now, we know how to write definitions for our own functions.

To sum up, we can write a function because:

  1. Given any thing, we know how to make it awesome.
  2. It follows a formula: scale 2 2 (color chartreuse ____________) where you just fill in the blank.

If both of those are true, you can write a function definition.  It looks like like the variable definitions we’ve written before, except that it has parameters.  A parameter is any word that comes before the equal sign (=), except for the first one.  In the function we wrote a minute ago, we called the parameter x.  Parameters are just placeholders, so when you use the function, you’ll give it an argument, that argument gets stuck in where ever that variable name pops up.

We also talked about what it means to be cute, and came up with the following:

cute x = scale 0.5 0.5 (color purple x)

Let’s check our assumptions: given any shape you choose to define, we can draw a cute one.  It follows a definite formula (make it half the size, and color it purple).  And so we wrote a definition where the function is called cute, and the parameter is called x.  If you wanted to draw a cute elephant, you could define picture like this: picture = cute elephant.  There, the function is cute and the argument is elephant, so to figure out what that means you just replace x with elephant every time it shows up in the function definition for cute!

Section 2: In which elephants can move their tails…

Let’s look at another function.  We know how to draw an elephant… but there’s one problem.  No matter where we draw an elephant, its tail is always sticking out at exactly the same angle.  Suppose we want to be able to draw an elephant with its tail sticking in whatever direction we like.

It turns out that almost all of drawing an elephant will remain the same, but there’s one rotate where we’ll want to change the angle.  So once again, we have:

  1. For any angle, we can draw an elephant with its tail at that angle.
  2. How we draw an elephant follows the same formula each time, except for a different number in that one place.

Sounds like a job for a function!

elephant angle = pictures [
      rotate (-20) (scale 3 2 (translate 30 40 (circleSolid 25))),
      translate 150 (-20) (rectangleSolid 40 80),
      translate (-10) 40 (scale 1.5 1 (circleSolid 80)),
      translate 50 (-50)(rectangleSolid 40 70),
      translate (-60) (-50) (rectangleSolid 40 70),
      translate (-125) 50 (rotate angle (translate 0 20 (rectangleSolid 10 40)))
      ]

See how that worked?  Most of the elephant stayed the same, but the rotate in the last line uses the parameter, angle.  So whatever number we give it decides with way the tail points.  It could be straight up…

picture = elephant 0

or it could be mostly down…

picture = elephant 160

So once again, we’re able to use functions: this time to say how to draw an elephant, but leave until later the question of which direction its tail should be pointing.

Section 3: Lists, Lists Everywhere

The interesting thing about functions was that they have parameters, which are special variables that can have different values depending on how you use the function.  There’s another way that something similar can happen, and it’s in lists.  So we’ll finish off by looking at some more kinds of lists.

The lists we’ve used so far have all looked something like this:

[ 1, 2, 3, 4, 5 ]

In other words, a list has always had an opening bracket, then some elements (that is, things in the list) separated by commas, and finally a closing bracket.  The things in the list haven’t been numbers… we’ve worked with lists of pictures, and lists of points!  You can have lists of whatever you want, but the form is the same: you still have the brackets and the commas.  We can call these “simple lists”, because, they are pretty easy to use.

A second kind of list that will come in handy, that we haven’t used before, is a range.  That looks like this:

[ 1 .. 10 ]

It always has an opening bracket, a first element, two dots in a row, and then a final element, and a closing bracket.  This kind of list counts for you.  The things inside (for now, at least) always have to be numbers so that you can count… and the computer will fill in the middle of the list for you.  In this case, the list we defined is the same as [1, 2, 3, 4, 5, 6, 7, 8, 9, 10].  The range is just a shorthand.

There’s one more simple trick we can play, too: we can give the first two elements, and the computer will continue the pattern:

[ 2, 4 .. 10 ]

This look almost like a range, except that we’ve given the first two elements, instead of the just the first one.  The computer will notice that we skipped forward by two, and will keep doing that, so that list is the same as [2, 4, 6, 8, 10]!

Finally, we get to the most interesting kind of list of all: called a list comprehension.  Here’s an example:

[ x + 7 | x <- [1 .. 5] ]

This has quite a few parts, so let’s go through them carefully:

  • It starts with an opening bracket, just like all lists.
  • Next is an expression.  Notice that the expression has a variable x that we haven’t mentioned yet.  That’s okay, it’s coming later.
  • In the middle, there’s a vertical bar (shift + backslash).  That separates the expression from the next part.
  • Now we have a sort of definition of x, except we say that x is any thing from another list!  We do that with a backwards arrow, which is typed as a less-than sign, followed by a dash.
  • Finally, there’s a closing bracket.

What this means is: give me a list of all values of (x+7), where x is any of the numbers in that list.  So this is equivalent to [1+7, 2+7, 3+7, 4+7, 5+7]… and of course that is the same as [8, 9, 10, 11, 12].

This last kind of list is very, very interesting; but maybe right now it just looks very complicated and you can’t see why.  To see how it’s interesting, we’ll start writing some lists of pictures, instead of just numbers.

Section 4: Combining List Comprehensions and Pictures

The last thing we did this week is combine pictures and list comprehensions to make some interesting pictures.  I’ll give you a bunch of examples, but not the pictures they draw.  Your task is to first try to guess what the picture will look like, and then try them out using the gloss programming web site and check your guesses.

I’d very strongly encourage you to take this seriously… use graph paper, work it out, and do your best to figure out what is going to be drawn before you run the program and check.

First example:

picture = pictures [
    circle x
        | x <- [ 10, 20 .. 100 ]
    ]

Second example:

picture = pictures [
    translate x 0 (circle 20)
        | x <- [ 0, 10 .. 100 ]
    ]

Third example

picture = pictures [
    translate x 0 (circle x)
        | x <- [ 10, 20 .. 100 ]
    ]

Fourth example:

picture = pictures [
    rotate x (rectangleWire 300 300)
        | x <- [ 0, 10 .. 90 ]
    ]

Fifth example:

picture = pictures [
    translate x 0 (rotate x (rectangleWire 300 300))
        | x <- [ -45, -35 .. 45 ]
    ]

We can also put several different variables on the right side of the vertical bar, separated by commas.  In that case, we’ll get something in the list for each possible combination of those variables!  We can use that, too…

Sixth example:

picture = pictures [
    translate x y (circle 10)
        | x <- [ -200, -100 .. 200 ],
          y <- [ -200, -100 .. 200 ]
    ]

Seventh example:

picture = pictures [
    rotate angle (translate x 0 (circle 10))
        | x     <- [50, 100 .. 200 ],
          angle <- [ 0,  45 .. 360 ]
    ]

Eighth example:

picture = pictures [
    rotate angle (translate (5*x) 0 (circle x))
        | x     <- [10, 20 ..  40 ],
          angle <- [ 0, 45 .. 360 ]
    ]

As you can see, you can use list comprehensions to make lots of really cool pictures where it would be really tedious to write out each shape the way we’ve been doing before.

Your Assignment

Your assignment this week is to pick a picture with a lot of repetition that you can draw with list comprehensions, and build it.  If you are in the United States and don’t have another idea, a really good one is the American flag!

Hints:

  • There’s a program to draw a star at the beginning of this summary.  You can copy the star part from that if you like.
  • You’ll probably have to draw the stars in two groups: first, there’s a 5-row, 6-column bigger grid, and then there’s a 4-row, 5-column smaller grid inside of that.

You don’t have to draw a flag, though!  Especially if you’re not in the United States, your flag probably doesn’t repeat as much as ours, so you’ll want to pick something different.  Just pick something you can draw by using list comprehensions to make lists of pictures.

Have fun!

A Reference

One last thing… I’ve put together a reference card about the recent things we’ve done: lines, polygons, and types of lists.  This might be a good thing to keep around.  Click below to grab a copy.

September 10, 2011 / cdsmith

Haskell For Kids: Week 4

Welcome back to our weekly report on the Haskell for Kids class!  We did three big things this week, so let’s just jump in!

New Student!

First of all, we gained a student in my class, so we all welcomed Skyler!  We’re three weeks in, but this gave us a great chance to go back over some of the basic ideas we’ve already seen.  These include:

  1. The first week, we talked about what computer programming is, what a compiler is, and what a library does for you.  We also introduced the basics of programming using the Haskell programming language and the Gloss library, and we played around.  So we reviewed the basics of that.  Here’s a link to the Week 1 Summary.
  2. The second week, we talked about the basic structure of a program, including what an import statement means, how to write definitions of variables, and the idea of expressions.  We also looked at how useful it is to stay organized and make sure everything in your program is where it belongs.  Here’s a link to the Week 2 Summary.
  3. Finally, the third week, we talked about cartesian (x,y) coordinates and lines and polygons, and we practiced “playing computer” and predicting what the computer is going to draw when it sees programs we made up.  Here’s a link to the Week 3 Summary.

Skyler joining gave us a chance to go back and review that, and practice explaining it to someone new.  I think most people learned something new of their own, too.

Practicing Top-Down Design

Another thing we did this week was practice some of the ideas we’ve touched on briefly in the past:

  • Top-down design
  • Organizing and naming things
  • Writing stubs

We did this by working through an example in class, in great detail.  I’ll try to reproduce that here.  You can follow along, as always, at http://dac4.designacourse.com:8000/  Remember, the point of this isn’t just to skip ahead and look at the final result: it’s to follow through the steps of how we got there.  We used techniques that you can use to try to write your own programs, too!

It does get repetitive, though, so at each step (except the last), I’ve bolded the parts of the program that are new, so you can generally ignore anything that’s not in bold because you’ve seen it before.

The Goal

Our goal will be to draw a dinner plate.  Here’s a whiteboard drawing of our goal:

We’ll start out by writing a basic program to draw an empty picture.  We may not have used it before, but blank is defined by Gloss to be an empty picture.

import Graphics.Gloss

picture = blank

If we run this program, the result looks rather boring…

So far, so… boring.  But there’s something worth pointing out.  Defining picture to be blank was called a “stub”.  We just stuck something in to make the program complete, knowing it was obviously not enough.  That’s okay, so long as we remember the places we’ve used stubs so we can go back and fill them in later.

The first thing we’ll do is declare that our picture is a dinner.  That looks something like this.  We’ll also start adding comments (remember, those of bits of the program that are ignored by the computer) to remind ourselves where we’ve got stubs.

import Graphics.Gloss

picture = dinner
dinner = blank -- stub 

This looks the same as before; we’ve just said that the picture is a dinner… and that a dinner is blank.  It might seem pointless, but don’t underestimate the chance to name things!  This will come in handy later.

Let’s fill in the stub for dinner with the major parts of the dinner we’d like to draw.  If you look at the plan, you can see it’s roughly divided into a plate, some food, a knife, and a fork.  I’ll throw in a table, too, which is just the background for the entire image.  Here’s our attempt to expand on the program:

import Graphics.Gloss

picture = dinner

dinner = pictures [
 table,
 plate,
 food,
 fork,
 knife
 ]

table = blank -- stub
plate = blank -- stub
food = blank -- stub
fork = blank -- stub
knife = blank -- stub

This might not look impressive when it’s done, but we’re working on understanding how to break down the picture into pieces.  Let’s pick out a few easy pieces to draw, now.  First, the table is just a 500 by 500 rectangle (in other words, the entire screen), colored a good table color, like brown.

import Graphics.Gloss

picture = dinner

dinner = pictures [
    table,
    plate,
    food,
    fork,
    knife
    ]

table = color brown (rectangleSolid 500 500)
plate = blank  -- stub
food  = blank  -- stub
fork  = blank  -- stub
knife = blank  -- stub

Let’s compile and run that…

Not in scope: `brown'

Oops!  We used the color brown, but that’s not defined by Gloss.  We can define it, though.  Brown is, generally speaking, a dark orange, so let’s say so:

import Graphics.Gloss

picture = dinner

dinner = pictures [
    table,
    plate,
    food,
    fork,
    knife
    ]

table = color brown (rectangleSolid 500 500)
plate = blank  -- stub
food  = blank  -- stub
fork  = blank  -- stub
knife = blank  -- stub

brown = dark orange

Now we’ll try again.

Looks good!  Time to add the plate.  We want to draw a rim on the plate, so it will consist of two circles — one on top of the other, and a little smaller.  We’ll also want two new colors: gray and lightGray.  This shouldn’t be difficult, so we’ll write it.

import Graphics.Gloss

picture = dinner

dinner = pictures [
    table,
    plate,
    food,
    fork,
    knife
    ]

table = color brown (rectangleSolid 500 500)

plate = pictures [
 color gray (circleSolid 175),
 color lightGray (circleSolid 150)
 ]

food  = blank  -- stub
fork  = blank  -- stub
knife = blank  -- stub

brown     = dark orange
lightGray = dark white
gray = dark lightGray

I did something a little tricky with the colors.  I could have defined gray to be dark (dark white), but it was easier to use the other color, lightGray, that I’d already defined.  Either one would mean the same thing.  Can you see why?

We’ll now build and run this program, and check the result.

As you can see, this is coming along fine.  Time to do something about that silverware that’s stubbed out.  What do we know about it?  Let’s make a list:

  • We want a fork and a knife, both.
  • We want them to be in the middle vertically, but on different sides, about 200 pixels over.
  • They will be much taller than they are wide… maybe 300 pixels tall, but only 50 wide.

We’ll stop there, rather than trying to do everything at once.  Remember, the idea is to work in small steps, filling in a few details at a time.  So for now, we’ll ignore the unique shapes of forks and knives, and just make them rectangles.  Because where we put the fork and knife isn’t really a part of what it means to be a fork or knife, those translations should go in dinner, not fork or knife.  The result looks like this.

import Graphics.Gloss

picture = dinner

dinner = pictures [
    table,
    plate,
    food,
    translate ( 200) 0 fork,
 translate (-200) 0 knife
    ]

table = color brown (rectangleSolid 500 500)

plate = pictures [
    color gray      (circleSolid 175),
    color lightGray (circleSolid 150)
    ]

food  = blank                 -- stub
fork = rectangleWire 50 300 -- stub
knife = rectangleWire 50 300 -- stub

brown     = dark orange
lightGray = dark white
gray      = dark lightGray

Notice that I’ve stilled marked fork and knife as stubs.  They are!  That’s certainly not what they look like.  But it just helped to draw an outline of the region of the plate where they belong.  Let’s compile and run this, and see what happens.

It’s about time we start filling in the food.  We’ll start out by breaking it down into the three main pieces, and then again stub them out with outlines rather than get into the details of what each piece looks like.  Each piece of food is translated and rotated a little.

import Graphics.Gloss

picture = dinner

dinner = pictures [
    table,
    plate,
    food,
    translate ( 200) 0 fork,
    translate (-200) 0 knife
    ]

table = color brown (rectangleSolid 500 500)

plate = pictures [
    color gray      (circleSolid 175),
    color lightGray (circleSolid 150)
    ]

food = pictures [
 translate (-50) ( 50) (rotate ( 45) carrot),
 translate (-20) (-40) (rotate ( 20) broccoli),
 translate ( 60) (-30) (rotate (-10) broccoli)
 ]

carrot = rectangleWire 40 80 -- stub
broccoli = rectangleWire 80 80 -- stub
fork     = rectangleWire 50 300  -- stub
knife    = rectangleWire 50 300  -- stub

brown     = dark orange
lightGray = dark white
gray      = dark lightGray

Don’t worry if you couldn’t figure out all those numbers right off!  When we wrote this in class, we had to guess and then tweak them until the rectangles ended up in about the right places.  Being able to do that before we worry about the details of what broccoli is shaped like is one of the reasons we like stubs like this!  (Also, don’t worry if you didn’t know how to spell broccoli.  I had to look it up, too.)

Let’s run this and see what it looks like.

We’re now going to play our next trick.  We’d like to focus on how to draw a carrot.  But since the carrot is translated and rotated, it’s hard for us to focus on just that piece.  Remember when we wrote picture = dinner earlier?  I promised that would come in handy!  We’re going to, just for now, change that to say picture = carrot.  Our program now looks like this:

import Graphics.Gloss

picture = carrot

dinner = pictures [
    table,
    plate,
    food,
    translate ( 200) 0 fork,
    translate (-200) 0 knife
    ]

table = color brown (rectangleSolid 500 500)

plate = pictures [
    color gray      (circleSolid 175),
    color lightGray (circleSolid 150)
    ]

food = pictures [
    translate (-50) ( 50) (rotate ( 45) carrot),
    translate (-20) (-40) (rotate ( 20) broccoli),
    translate ( 60) (-30) (rotate (-10) broccoli)
    ]

carrot   = rectangleWire 40  80  -- stub
broccoli = rectangleWire 80  80  -- stub
fork     = rectangleWire 50 300  -- stub
knife    = rectangleWire 50 300  -- stub

brown     = dark orange
lightGray = dark white
gray      = dark lightGray

When we run this, we’ll have told the computer all about dinners and forks and knives and everything… but in the end, only asked it to draw a carrot.  That’s fine; the computer is happy to ignore our definitions of variables that we don’t really use!  The result looks like this.

So we’ve gotten rid of everything except the carrot, which of course looks like just a rectangle for now.  Having escaped from the distractions of forks and broccoli, it shouldn’t be too hard to tell what a carrot is!  It’s just a polygon colored orange.  After some experimentation, you might end up with this:

import Graphics.Gloss

picture = carrot

dinner = pictures [
    table,
    plate,
    food,
    translate ( 200) 0 fork,
    translate (-200) 0 knife
    ]

table = color brown (rectangleSolid 500 500)

plate = pictures [
    color gray      (circleSolid 175),
    color lightGray (circleSolid 150)
    ]

food = pictures [
    translate (-50) ( 50) (rotate ( 45) carrot),
    translate (-20) (-40) (rotate ( 20) broccoli),
    translate ( 60) (-30) (rotate (-10) broccoli)
    ]

carrot = color orange (polygon [
 (-5, -40), (-20, 40), (20, 40), (5, -40)
 ])

broccoli = rectangleWire 80  80  -- stub
fork     = rectangleWire 50 300  -- stub
knife    = rectangleWire 50 300  -- stub

brown     = dark orange
lightGray = dark white
gray      = dark lightGray

That looks like this:

Now, having gotten the look of a carrot under control, let’s change the definition of picture, so that the entire dinner will be drawn again.

import Graphics.Gloss

picture = dinner

dinner = pictures [
    table,
    plate,
    food,
    translate ( 200) 0 fork,
    translate (-200) 0 knife
    ]

table = color brown (rectangleSolid 500 500)

plate = pictures [
    color gray      (circleSolid 175),
    color lightGray (circleSolid 150)
    ]

food = pictures [
    translate (-50) ( 50) (rotate ( 45) carrot),
    translate (-20) (-40) (rotate ( 20) broccoli),
    translate ( 60) (-30) (rotate (-10) broccoli)
    ]

carrot = color orange (polygon [
    (-5, -40), (-20, 40), (20, 40), (5, -40)
    ])

broccoli = rectangleWire 80  80  -- stub
fork     = rectangleWire 50 300  -- stub
knife    = rectangleWire 50 300  -- stub

brown     = dark orange
lightGray = dark white
gray      = dark lightGray

Hopefully, you can see how this will end up.  One by one, for each of the remaining pieces of the program, we’ll do three things:

  1. Change the definition of picture to focus on that piece.
  2. Write a program to properly draw that piece.
  3. Change the definition of picture again to draw the entire dinner.

In the interest of space, I’m skipping the remaining steps, but here’s the program we ended up with:

{-
    Picture of a dinner plate

    This program draws a dinner plate, with several food items and silverware.
-}

import Graphics.Gloss

picture = dinner

dinner = pictures [
    table,
    plate,
    food,

    -- Silverware:
    translate ( 200) 0 fork,
    translate (-200) 0 knife
    ]

table = color brown (rectangleSolid 500 500)

plate = pictures [
    color gray      (circleSolid 175),            -- rim
    color lightGray (circleSolid 150)             -- center
    ]

food = pictures [
    translate (-50) ( 50) (rotate   45  carrot),
    translate (-20) (-40) (rotate   20  broccoli),
    translate ( 60) (-30) (rotate (-10) broccoli)
    ]

carrot = color orange (polygon [
    (-5, -40), (-20, 40), (20, 40), (5, -40)
    ])

broccoli = color (dark green) (pictures [
    translate (  0) (-15) (rectangleSolid 30 50), -- base
    translate (-15) (  0) (circleSolid 25),       -- flower
    translate ( 15) (  0) (circleSolid 25),       -- flower
    translate (  0) ( 15) (circleSolid 25)        -- flower
    ])

fork  = color lightGray (pictures [
    rectangleSolid 10 250,                        -- handle
    translate (  0) ( 80) (rectangleSolid 40 10), -- base
    translate (-15) (100) (rectangleSolid 10 45), -- left prong
    translate ( 15) (100) (rectangleSolid 10 45)  -- right prong
    ])

knife = color lightGray (pictures [
    translate 0 (-25) (rectangleSolid 30 200),    -- handle
    polygon [ (-15,  75),
              ( -5, 105),
              ( 15, 125),
              ( 15,  75) ]                        -- blade
    ])

{-
    Some colors that are used in the picture:
-}
brown     = dark orange
lightGray = dark white
gray      = dark lightGray

(We also added some comments to explain a little more and divide up the program into sections.  And here is the final picture.

Voila!  We have finished.  The important thing to learn is how we were able to draw the whole picture by first just sketching out the major parts, and then filling in the details bit by bit.  That’s the idea of top down design, which is a very good way to go about writing computer programs.

Oh no!  Exam Time!

We’ve been working on and talking about pictures for a while, and some of us are getting antsy to move on to something else.  Before we can, though, we need to be sure we all understand the ideas we’ve learned in writing our picture programs.  So here it is: time to demonstrate a complete understanding of writing programs to draw pictures.  Time for our first exam!

Here’s the “exam” I assigned to the students in my class this week.  It’s due in class next week.  Don’t worry too much about it; the point is more to go back and review before we move on… we’re not failing anyone!

Instructions

This is what they are working on from now until next week, as a final bit of practice with pictures before we move on to animations.

  1. Pick one of the following four pictures.
  2. Write a program that draws a simplification of the picture on that page.  Write the program using top-down design, in the way we talked about earlier.
  3. As a rule of thumb, divide the overall picture into at least three pieces, and divide each of those into about two to four pieces each.  Part of the assignment is to pick out how to divide the picture into pieces, which details are important and which you can leave out.  Don’t try to draw everything in the picture.
  4. Use each of the following at least once in your picture:
    • A circle
    • A rectangle
    • A line or polygon (one or the other is fine)
    • Translate, rotate, and scale
    • Colors (pick whichever seem best)
    • Comments where appropriate to explain what you’re doing.

Remember: The goal isn’t just to get the computer to draw your picture.  It’s also to write a program that is easy to read and understand, looks clean and organized, and explains your picture well.  Be a good communicator.

About These Blog Posts

Okay, so it’s become clear that I am sometimes going to need the weekend to work on writing down what we do in class at length.  So, from now on, I’m going to stop calling this “late” and just say that I’ll plan on getting the blog post done by the end of the weekend.  I’m just changing the definition of “late” so that I’m not late any more.  Very clever, isn’t it?

Until next week, have fun, and feel free to ask questions in the blog comments.

September 5, 2011 / cdsmith

Games: Now Available in Gloss-Web

At long last, I can announce the game interface in gloss-web.  This is still a good ways off in my class, but those of you who know what you’re doing can play around with it anyway.  As always, you can visit

http://dac4.designacourse.com:8000

If you’ve used the site before and don’t see a game button, you may need to hit the refresh button.

How they work:

Games are similar to simulations, except that the time-step function has one fewer parameter, and there’s an additional event handling function.  So you’ll need to write the following:

initial :: StdGen -> a

Just as with simulations, you can pick any data type you like (and probably write your own) to represent the state of the world.  You then define initial to be a function that gets a random number generator, and returns the starting state.  If you need random numbers, you can store the generator in your state type.  The type variable a needs to be the same as a in all the definitions that follow.

event :: Event -> a -> a

Here’s how you respond to events: write a function with the event and the previous state of the world, that returns a new state of the world as its result.  That means anything you want to remember about the events that have happened should be part of your world type.

step :: Float -> a -> a

Here’s how you respond to the passage of time.  Much like the step function of the simulation interface, the time parameter is the amount of time that’s elapsed since the last step.  Unlike simulations, there is now ViewPort passed in.  That’s because in the OpenGL implementation, simulations automatically provided controls to zoom and such… but games don’t.  So you just get the elapsed time.  (Of course, gloss-web doesn’t provide those automatic transformations anyway.)

draw :: a -> Picture

Finally, of course you need to draw the world.  This is where you say what it looks like.

An Example

The default program is a fairly simple one that draws a ball where ever you place the mouse; not much of a game, really!  Never fear, here’s something a little more involved… and actually pretty fun!  My best score so far is 31.  Can you do better?

import Graphics.Gloss
import Graphics.Gloss.Interface.Game

data World = World {
    player :: Point,
    target :: Point,
    goal   :: Point,
    robot  :: Point,
    speed  :: Float,
    score  :: Integer
    }

initial _ = World (0,0) (0,0) (200,200) (-200,-200) 40 0

event (EventMotion (x,y)) world = world { target = (x,y) }
event _                   world = world

distance (x0, y0) (x1, y1) = sqrt ((x1 - x0)^2 + (y1 - y0)^2)

moveToward (x0,y0) (x1,y1) dist = (x0 + dx, y0 + dy)
    where totalDist             = distance (x0,y0) (x1,y1)
          dx | dist < totalDist = (x1 - x0) * dist / totalDist
             | otherwise        = (x1 - x0)
          dy | dist < totalDist = (y1 - y0) * dist / totalDist
             | otherwise        = (y1 - y0)

collisions world | distance (player world) (goal  world) < 40 = foundGoal
                 | distance (player world) (robot world) < 40 = initial
                 | otherwise                                  = world
  where foundGoal = let (x,y) = player world
                    in  world { goal = (-x, -y), score = score world + 1 }

step time world = collisions newWorld
  where
    newWorld = world {
        player = moveToward (player world) (target world) (time * 60),
        robot  = moveToward (robot world)  (player world) (time * speed world),
        speed  = speed world + (0.1 * time)
        }

draw world = pictures [
    color blue  (figure (player world)),
    color red   (figure (robot  world)),
    color green (figure (goal   world)),
    translate (-225) (-225) (scale 0.2 0.2 (text (show (score world))))
    ]

figure (x,y) = translate x y (circleSolid 20)

Have fun!

September 3, 2011 / cdsmith

Haskell For Kids: Week 3

Where We Are

We’ve gotten a lot done in just two weeks.  To sum up, we’ve done all of these:

  • Learned how computer programming works: all about compilers, programming languages, and libraries, and how they work together.
  • Wrote computer programs to describe pictures.  We described simple pictures like circles and rectangles.  We modified other pictures by stretching, rotating, and moving them around.  And most importantly, we combined smaller pictures into bigger and more complicated ones.
  • Used variables to give names to things in our program, like the individual parts of our pictures… like sun, elephant, and so on.
  • Saw for ourselves the importance of staying organized, giving things good names, keeping track of related ideas, and using comments (sections of your program that the compiler ignores) to make notes in your program.

If you like, you can review those ideas in Week 1 and Week 2.  Go on, we’ll wait for you.

Lines and Polygons

So far, we’ve been spending a lot of time drawing with circles and rectangles.  That’s been fun, but it’s also limiting.  What if you wanted to draw a star?  Maybe you could rig something up by stretching or rotating rectangles in the right ways, but it sure wouldn’t be easy!  We spent our second class last week talking about how to do something more flexible: lines and polygons.

Cartesian Coordinates

To understand lines and polygons, we’ll need a way to talk about specific places on the drawing.  We do that using something called cartesian coordinates.  The idea is to talk about a point by giving two numbers:

  1. How far from the middle of the painting, horizontally.  We call this the x coordinate.
  2. Haw far from the middle of the painting, vertically.  We call this the y coordinate.

Here’s a picture that might help (taken from Berkeley Science, here):

We write a point as (x,y) where x and y are the coordinates as above: x goes right or left, and y goes up or down.  The point in the very middle of the picture is called (0,0) because it’s immediately in the center both horizontally and vertically.  Other points can be found by following the x line (or “axis”) to the first coordinate, then moving up or down alongside the y line (the y “axis”) to the second coordinate.  Notice that we use negative numbers to mean “left” or “down”.

Exercise: Take a few minutes to pick some more points on the diagram, and see if you can write down their coordinates — that is, write them as a pair of numbers in parentheses just like the points already labeled.

If you remember, we said earlier that the drawing area on the gloss-web web site is 500 by 500 in size.  That means the center is still (0,0), but the numbers in your coordinates can range from -250 to 250.  (Why?  Because 250 is half of 500, and half of the size is on each side of the center.)  It might help at this point to get out some graph paper, and draw yourself a square, and see if you can find some points… like (100,100) or (-200, 50).  As a special bonus, you can also hover your mouse over the drawing area when you run your programs using gloss-web, and you’ll see a tool tip with the coordinates of the place your mouse pointer is.

Drawing Lines

Let’s use those coordinates to draw things.  Try out this program:

import Graphics.Gloss
picture = line [ (-100, -100), (-200, 50) ]

Can you guess at what the result will be?  Now run it, and see for yourself.  It drew a line from one point to the other.  You can also draw longer (jagged) lines by listing even more points.

import Graphics.Gloss
picture = line [
    (-200, -200),
    ( 200, -200),
    ( 200,  200),
    (-200,  200),
    (-200, -200)
    ]

Try to see where those points will end up on the drawing screen, and then what the result will be.  Now run it.  Did it do what you expected?

Drawing Polygons

Not only can you draw lines, but you can draw filled-in shapes as well.  These are called polygons, which are just a fancy word for shapes with straight edges as sides.  We can turn the previous example into a filled in shape:

import Graphics.Gloss
picture = polygon [
    (-200, -200),
    ( 200, -200),
    ( 200,  200),
    (-200,  200)
    ]

Notice that I didn’t need to repeat the last point like I did for the line.  That’s because shapes have to be closed off, so Gloss assumes that we meant to add a line back to where we started.  Of course, rectangles aren’t very exciting, so here’s a program that Ms. Sue wrote!

import Graphics.Gloss

picture = stars

stars = pictures [
    translate ( 100) ( 100) (color blue   star),
    translate (-100) (-100) (color yellow star),
    translate (   0) (   0) (color red    star)
    ]

star = polygon [
    (  0,  50),
    ( 10,  20),
    ( 40,  20),
    ( 20,   0),
    ( 30, -30),
    (  0, -10),
    (-30, -30),
    (-20,   0),
    (-40,  20),
    (-10,  20),
    (  0,  50)
    ]

Can you guess what that does?  Here’s the result.

Thinking Like a Computer

That’s what we did last week.  This week, we’re talking about how to think about computer programs from the computer’s perspective.  We’re going back over everything we’ve learned, but this time we’re pretending to be a computer, reading the programs and trying to interpret them.  Here’s what we’ve talked about so far:

Modules

When we write our computer programs in the web browser, we type everything into a text box and choose Run.  The whole thing we type into our text box is called a module.  So far, you can think of module as a word that means the entire program.  (We talked a little bit about how programs can have more than one module, too.  In fact, most programs in the world do!  But it will be a while before we’ll really need to separate our programs into more than one module.)

Modules have two kinds of things in them that we’ve seen so far:

  • Imports.  These always have to be at the beginning of the module, and they say what other modules (normally from libraries) we’re using.  For example, we always start our programs by importing Graphics.Gloss, because that gives us all the Gloss stuff, like circles and colors and so on.  We normally only import one library, but if you needed to, you could import more than thing.
  • Definitions.  A definition tells the computer what a word (called a variable) means.  For example, if you look at the star program earlier, there are three definitions: for the words “picture”, “stars”, and “star”.

An import always starts with the special word “import”.  A definition for a variable always has the name of the variable you’re defining, an equal sign, and the thing you’re defining it to mean.  Sometimes in the past, we’ve seen people try to add other stuff to a module that are not imports or definitions.  For example, maybe you’ve tried to write something like this:

import Graphics.Gloss
circle 80

If you’ve tried that, you know it doesn’t work!  You can’t throw in a description of the circle just anywhere in your program.  The error you’d get for that would say “Naked expression at top level”.  When you see that, it means you forgot to say what variable you are defining!

How To Be A Compiler

Here’s what the compiler does: it reads your program, and remembers what words you’ve defined.  Then it know a specific word it wants to look up the meaning of.  For us, that specific word is “picture”.  So it consults your program, and looks up the meaning of “picture”.  Then, if there are any words that occur in there that the compiler doesn’t know, it tries to look those up, too.  As long as there are words it doesn’t know, it keeps looking them up!  Basically, when you write a computer program, you’re giving the compiler a dictionary to look up words in.

With that in mind, think about the next program.

import Graphics.Gloss

picture = color myFavoriteColor (circle 100)

myFavoriteColor = blue

stars = pictures [
    translate ( 100) ( 100) (color blue   star),
    translate (-100) (-100) (color yellow star),
    translate (   0) (   0) (color red    star)
    ]

star = polygon [
    (  0,  50),
    ( 10,  20),
    ( 40,  20),
    ( 20,   0),
    ( 30, -30),
    (  0, -10),
    (-30, -30),
    (-20,   0),
    (-40,  20),
    (-10,  20),
    (  0,  50)
    ]

If you are a compiler and see this program, what do you do?  Here’s what:

  • You see the import, and make a note that this program uses the Gloss library.  You can then go see what’s in the Gloss library, and you’ll see that there are definitions for things like “circle” and “rectangleSolid” and “polygon” and “green”.  You now know what these words mean.
  • You then see the definitions in this module.  There are three of them: “picture”, “stars”, and “star”.
  • Since your goal in life is to go find out what “picture” means and draw it, you read the definition, and try to understand it.
  • Oops, you don’t know what “myFavoriteColor” means!  Not a problem; you go look that up, and find out that it means blue.
  • Now you know everything you need about what “picture” means, and you’re done.  You go and draw a blue circle.

You might wonder, what about “stars” and “star”?  Well, you know what they mean… but they never came up.  Just because a word is in the dictionary doesn’t mean you necessarily need it.  Remember, the compiler only uses the parts of your program that it needs to draw the thing you’ve called “picture”.  If you want to see a shape, you need to make it part of the definition of picture (or of some other word that happens in picture, and so on).

Expressions (and we don’t mean smiles!)

We can talk a little bit more about the things that come after the equal signs in definitions.  These are called expressions, and there are several forms of them we’ve used.  You have seen all of these before, but it will help to review them.

  • Variables.  A variable name (something that you’ve defined, or something that comes from a library) can be an expression.  To find out what it means, you’d look up the definition.  Examples of this are picture or green.
  • Functions (with arguments).  Another kind of expression we use a lot is a function, along with its arguments (also sometimes called parameters). Examples of this are circle 100, or translate 50 50 star.  Remember that each function expects a certain number of parameters, and you have to give it that many!
  • Lists.  A list is a bunch of things in square brackets, separated by commas.  We’ve seen them in two different places now: the parameter to pictures is a list of other pictures.  The parameter to line or polygon is a list of points.
  • Points.  A point is a pair of coordinates in parentheses, with a comma between them.  You need them in line and polygon, to go in the list of points you give it.
  • Numbers.  A number is written as just itself, like 5 or 1.75.
  • Strings.  Remember with text, where we put things in quotes after it?  That’s a form of expression too: a string.

You might have noticed that not all the forms of expressions give you pictures!  Some of them give you numbers, or points, or lists.  It’s up to you to make sure that you’re putting the right type of expression in the right places.  If you try to define picture to be the number 7, for example, it won’t work!  That’s because 7 isn’t a picture… it’s just a number.

Now, here’s where things get interesting: Some of those kinds of expressions have smaller parts… and those smaller parts are expressions too!  So we build up expressions out of other, smaller expressions.

How about an example?  Let’s look at Ms. Sue’s stars program from earlier.  Here it is again, so you don’t have to scroll so far.

import Graphics.Gloss

picture = stars

stars = pictures [
    translate ( 100) ( 100) (color blue   star),
    translate (-100) (-100) (color yellow star),
    translate (   0) (   0) (color red    star)
    ]

star = polygon [
    (  0,  50),
    ( 10,  20),
    ( 40,  20),
    ( 20,   0),
    ( 30, -30),
    (  0, -10),
    (-30, -30),
    (-20,   0),
    (-40,  20),
    (-10,  20),
    (  0,  50)
    ]

There are three definitions: picture, stars, and star.

The picture definition is easy.  We say that picture means the expression with just one thing in it: the variable stars.  So a picture is the same thing as a stars.  You can define synonyms like this all over the place!  Marcello noticed that you could write:

move = translate

And then you don’t have to remember what translate means any more.  (I think you should remember what translate means, though.  Defining a new word for it might help you in the short term to write your program, but it won’t help at all when you need to read someone else’s program!)

Let’s look at star, which is a little bit longer.  The expression used for star is a function with arguments: the function is polygon, and there is one argument.  Remember, that argument is an expression of its own!  In particular, it’s a list, which means it’s a bunch of things separated by commas, surrounded by square brackets.  We can go deeper, though: each of the things in the list is yet another smaller expression: in this case, a point.  And finally, each of the coordinates in a point is yet another expression, which is a number.  So we have expressions within expressions within expressions within expressions!  That’s normally how things go: you do a lot of building up expressions in computer programming.

I’ve been saving the most complicated one for last.  Let’s take a look at stars.  This time, I’ll describe the expression using a bulleted list, and I think you’ll see why.

  • At the top level, stars is defined to mean a function with arguments…
    • The function is pictures, which is a variable.  So it has no smaller pieces.
    • The argument is a list — a bunch of things in square brackets, separated by commas…
      • The first thing in the list is a function with arguments…
        • The function is translate.  That’s just a variable; it has no smaller parts.
        • The first argument is 100.  It’s a number, and has no smaller parts.
        • The second argument is also 100, and has no smaller parts.
        • The third argument (which means the picture to draw) is another function with arguments.
          • The function is color, a variable.
          • The first argument is blue, which is a variable.
          • The second argument is star, which is also a variable.
      • The second thing in the list is a function with arguments…
        • The function is translate, a variable.
        • The first argument is -100, a number.
        • The second argument is -100, a number.
        • The third argument is another function with arguments.
          • The function is color, a variable.
          • The first argument is yellow, a variable.
          • The second argument is star, a variable.
      • The third thing in the list is yet another function with arguments.
        • The function is translate, a variable.
        • The first argument is 0, a number.
        • The second argument is 0, a number.
        • The third argument is another function with arguments.
          • The function is color, a variable.
          • The first argument is red, a variable.
          • The second argument is star, a variable.

That was long!  But can you look over it, and see how we can break down the expression into pieces, and each of their pieces is another expression?

Understanding Programs

The last thing we did this week, and also your homework, was to try to predict the results of some programs.  Here’s how this works.

  1. You’ll need some graph paper — you know, the kind with little squares all over it.
  2. Draw a square on your graph paper… maybe make it 10 boxes to a side.
  3. Draw a dot right exactly in the middle of your square.  This is the point (0,0).

If you made your square 10 boxes to a side, then each box is a distance of 50.  See if you can find some points in your square.

  • Find the point (250, 250).
    • (You should have come up with the top right corner of the box.)
  • Find the point (0, -250).
    • (You should come up with the point in the middle of the bottom edge.)

Now your goal will be to read some programs, and try to draw what they would draw.  You can check your answers using the programming environment.  Be careful, though.  If you submit one of these programs, your computer will forget the program you’ve been working on, so be sure to save a copy of that somewhere first!

Exercise 1: Draw the following.

import Graphics.Gloss
picture = rotate 45 (rectangleWire 150 150)

Exercise 2: Draw the following.

import Graphics.Gloss
picture = rotate 135 (pictures [
    circle 50,
    rectangleWire 10 100
    ])

Exercise 3: Draw the following.

import Graphics.Gloss
picture = translate 50 0 (rotate 45 triangle)
triangle = line [ (0,0), (100,200), (-100,200), (0,0) ]

Exercise 4: Draw the following.

import Graphics.Gloss
picture = rotate 90 (translate 100 0 (circle 100))

After you’ve tried those, try making up some expressions of your own, and predict what they are going to do.  We’re spending some time on this, because before we can move on to animations, it’s important to see what your programs mean!

That’s all until next week.

August 23, 2011 / cdsmith

Haskell For Kids: My Project!

Oops!  I almost forgot to do my own homework from my Haskell for Kids class!

Here’s the program I wrote (intentionally using only the features we’d already talked about in class.)

import Graphics.Gloss

picture = pictures [
    color lightGray (rectangleSolid 500 500),
    translate  0 (-75) (color darkGray mouse),
    translate 90 (150) thoughtBubble
    ]

darkGray = light black
lightGray = dark white

thoughtBubble = pictures [
                            (scale 100 50 filledCircle),
    translate ( -85) ( -15) (scale 0.4 0.4 (text "I wonder...")),
    translate ( -85) ( -65) (scale 20 20 filledCircle),
    translate (-120) (-110) (scale 15 15 filledCircle)
    ]

filledCircle = pictures [
    color white (circleSolid 1),
    color black (circle 1)
    ]

mouse = pictures [
    scale 2   1 (circleSolid 50),
    translate (-100) ( 40) mouseHead,
    translate ( 120) (-20) mouseTail,
    translate ( -40) (-55) mouseLegs,
    translate (  20) (-55) mouseLegs
    ]

mouseHead = pictures [
    translate 20 35 (color rose (circleSolid 20)),
    translate 20 35 (thickCircle 5 40),
    rotate (-10) (scale 1.5 1 (circleSolid 40))
    ]

mouseTail = (rotate (-15) (rectangleSolid 100 5))

mouseLegs = pictures [
    rectangleSolid 5 35,
    translate 20 0 (rotate 10 (rectangleSolid 5 35))
    ]

And the result:

August 23, 2011 / cdsmith

Haskell for Kids: Week 2!

It’s time for the second weekly roundup from my Haskell programming class for kids!  (Here’s a link to last week’s.)

Pictures From Last Week

Remember, last week’s assignment was to write a program to draw an involved picture about something of your choosing.  Here are some of the results:

This Week: Organization

The theme for this week is organization.  One problem that’s easy to run into quickly in computer programming is that you write computer programs that are so involved and complicated that you get stuck: the program might even work, but it’s so hard to understand that you dread having to change it!  We spent some time talking about ways to organize your computer programs to make them easier to read.

Parts of a Program

Just to review, a computer program that you wrote on the first day of class might look like this:

import Graphics.Gloss

picture = color red (pictures [ circle 80, translate 50 100 (rectangleSolid 100 50) ])

We looked a little closer at how programs are built during our second class last week.  Here are the parts.

Import Statement

The first line is the import statement: remember that’s where we tell the computer that we will be using the Gloss library.  If it weren’t for that line, then the computer would have no idea what words like color, red, pictures, circle, and so on actually mean!  You only have to import a library once, no matter how many times you use the things that it defines.

Definitions

After the import statement, your program defines some new words, called variables.  The one variable we defined in the program earlier was picture.  For the moment, we always define a variable called picture, because that’s how the computer knows what to draw.  What we didn’t mention in my last post, though, is that you can define other variables besides picture!  And when you do, you can use them in the same way you could use circle or other built-in picture types.

For example, look at this program:

import Graphics.Gloss

picture = snowman

snowman = pictures [
    translate 0 ( 50) top,
    translate 0 (  0) middle,
    translate 0 (-75) bottom
    ]

top    = circleSolid 50
middle = circleSolid 70
bottom = circleSolid 90

This program defines five variables: picture, snowman, top, middle, and bottom.  Again, the computer is only going to draw the thing labeled picture, but the other variables are useful for keeping things organized.  There are two important rules here, which are part of the programming language, Haskell:

  1. Each new definition has to start in the left-hand column.  It should not be indented.
  2. If you start a new line in the same definition, you have to indent it.  It doesn’t matter how far, but you need to indent at least a little.

It came up that I’m defining picture first, and then snowman, and so on… some people thought it would make more sense to do it in the other order.  That’s fine!  The order of your definitions makes no difference at all, so feel free to start with picture and work your way down to the parts (sometimes called “top down”, or to start with the parts and work your way up to the overall picture (sometimes called “bottom up”), in whatever way makes sense to you.  You could even put them in alphabetical order.  The computer doesn’t care.  (I don’t actually recommend alphabetical order… but you could!)

Expressions

The parts after the equal sign (=) in your definitions are called expressions.  This is where you say what the variables actually mean.  Most of what we looked at last week had to do with the different kinds of expressions you can put there: circles, rectangles, and so on, and even some more complicated expressions involving color or translate and so on.

In our second class last week we said a little bit more about what an expression is.  Look at this example:

picture = translate 10 20 (circleSolid 50)

The expression on the right side of the definition of picture has four parts to it, all written next to each other.  When you see something like that, the first part is called a function, and then rest of them are called parameters.  So here we have:

  1. translate - That’s the function
  2. 10 – That’s the first parameter
  3. 20 – That’s the second parameter
  4. (circleSolid 50) – That whole thing is the third parameter

Pay attention to the parentheses!  Parentheses mean “treat this whole part here as just one thing”.

Every function expects a certain number of parameters.  For example, translate always expects three: the first is how far to move horizontally, the second is how far to move vertically.  The third is the picture that you’re moving.  If you tried to give it only 2 parameters, or 5 parameters, it won’t work!  (If you want to, try it and see what happens.)

What about the part inside the parentheses?  It’s just another expression!  Can you identify which part of it is the function, and which are parameters?

There’s one other piece: you might notice that pictures is a bit different.  The piece that comes after pictures has square brackets around it, and you can have as many things in there as you like, with commas between them.  That’s just another kind of expression, called a list.  So far, pictures is the only thing we’ve seen that uses lists, but we’ll see another one soon!

Here’s the whiteboard after we discussed the parts of a program and expressions:

The conversation bubble was a different discussion: we talked about how you can make interesting shapes by drawing in white over the top of another shape.

Some Advice

Most of that was from the second class last week.  This week, we spent some time talking about good advice for writing computer programs.  We came up with the following:

Be Fanatical about Organization

If you don’t stay organized, it’s just not possible to write interesting computer programs.  Your programs should be designed out of pieces, and you should pick those pieces to be meaningful.  Here’s an example of what not to write:

import Graphics.Gloss
pictures = [
    translate 71 123 (rectangleSolid 30 200),
    rotate 45 (translate 10 1 (color green (circle 50))),
    translate 100 100 (scale 2 2 (rectangleWire 10 10)),

... and on, and on, and on ...

That's okay to do when you're trying things out or playing around.  But eventually, you want to break up your program into manageable pieces!  A long list of 40 different drawing operations isn't very fun to read, and it definitely isn't fun to try to make changes to later on.

Instead, try to do something like the snowman example earlier: the pieces of the snowman are broken down into smaller pieces, so you can think about one thing at a time.  Of course, not just any pieces will do!  You don't want one piece to have the grass and one leg and sun, and then then next piece to have another leg and a tree!  Try to find pieces of your picture that make sense on their own.  Computer programmers even have a fancy word for that: we call those pieces coherent or we say that they have a lot of cohesion.

Earlier, we mentioned the ideas of "top down" and "bottom up" approaches to programming: you can either start by defining picture, and then define its pieces... or you can start by defining the pieces, and then build bigger things out of them.  For now, whichever direction you find easier is okay, but just pay attention to which one you're doing, and maybe taking the opposite approach once in a while will make certain things easier.

Be a Good Communicator

The second piece of advice we talked about is to be a good communicator.  You're not just writing a computer program for the computer to run it: you're also writing something for other people to read.  You might show your programs to other people in the class, or to teachers, or plenty of other people.

A really good way to communicate well is to pick good names for things.  If you're drawing a flower, your program will be a lot easier to understand when your variables are called leaf, stem, and petal; not picture1, picture2, and picture3!

Another tool you can use that's helpful for communicating well is called comments.  The computer will ignore any part of your program that's between a {- and a matching -}.  (That's an open curly brace following immediately by a dash... and then a dash followed by a closing curly brace.)  For shorter comments, the computer will ignore anything from -- (two dashes in a row) to the end of the line.  So you can write something like this:

{-
    Picture of my dog, by Chris Smith

    This is a picture of my dog, Ruby.  She is part border collie.
-}

picture = pictures [
    circleSolid 50,       -- That's her body
    rectangleSolid 20 100 -- That's her tail
    ]

(No, that doesn’t really look much like a dog… gimme a break, it was just a quick example!)

By picking good names and adding comments to explain what you’re doing, you can make your programs a lot easier to read and understand, both for yourself and other people.  That’s what we mean by being a good communicator.

Hide Unimportant Ideas

There’s only so much that one person can remember at a time!  Because of that, another important idea in computer programming is to hide the stuff that isn’t important, so that you can focus on what is.

We talked about a new language feature that helps here, and that is let and where.  Here’s ax example of using where in a program.

import Graphics.Gloss

picture = snowman

snowman = pictures [
    translate 0 ( 50) top,
    translate 0 (  0) middle,
    translate 0 (-75) bottom
    ]
  where
    top    = circleSolid 50
    middle = circleSolid 70
    bottom = circleSolid 90

That is almost the same snowman program as before: but with one difference.  The variables top, middle, and bottom are defined after the word where, and still inside the definition of snowman.  (It might not be obvious here, but the word where is still indented by a few spaces, so it’s still part of the definition of snowman.

What this does is make top and middle and bottom only mean something inside of the definition of snowman.  So you can use them when you’re defining snowman, but if you tried to use them in a different part of your program, it wouldn’t work.  The error message you’d get would say “not in scope”.

The idea of scope is important in computer programming.  The scope of a variable is how much of the program it can be used in.  When you write more involved programs, you don’t want every single variable that you define to be visible everywhere!  As this snowman program gets bigger, maybe we might want the same name, like top, to mean something completely different when we’re drawing a different part of the scene.  That’s okay, because this top is only “in scope” during the definition of snowman.

We talked about an analogy for this: if you’re in England, it makes perfect sense to say “I saw the queen today!”  But, if you’re in the United States, it doesn’t make sense any more, because we don’t have a queen.  The phrase “the queen” means something different depending on where you are!  So if I talked like the Haskell programming language, and you said to me “I saw the queen today!”, I might say in response, “Not in scope: the queen”.

By the way, here’s the way to write that same snowman program but using let instead of where.

import Graphics.Gloss

picture = snowman

snowman =
    let top    = circleSolid 50
        middle = circleSolid 70
        bottom = circleSolid 90
    in  pictures [
            translate 0 ( 50) top,
            translate 0 (  0) middle,
            translate 0 (-75) bottom
            ]

This means exactly the same thing: you just get the choice between defining the pieces first (that’s let) or defining the pieces afterward (that’s where).

Pay Attention To Details

Finally, the last piece of advice we had for computer programming was to pay close attention to details.  There are lots of situations where a normal person might be able to figure out what you want, but your computer program still won’t work if you don’t get all the details right!

We looked at some of these details more closely:

  • Indentation:  You are not allowed to indent the first line of a definition.  You must indent every line after that.  These are rules in the Haskell programming language; if you don’t follow them, your programs won’t work.  Also, if you use let and where, then you have to indent all the definitions there by the same amount.
  • Parentheses: A lot of people have trouble with this when they get started with programming.  (For that matter, most of us still make mistakes with parentheses even when we’ve been programming for years!)  You have to match up your opening and closing parentheses, or your program just won’t work.We talked about a few things that help.  Some programming tools, including the web site we’re using right now, will help you match up parentheses by pointing them out.  Using the web site, try putting your cursor right after a parenthesis: the matching one will have a gray box drawn around it!  This can help a lot… but it’s only there if the tool you’re using happens to do it.We also talked about counting parentheses.  There’s a trick most programmers figure out for checking their parentheses: start out with the number 0 in your head, and then read through part of your program, and add one every time you see an open parenthesis, and subtract one every time you see a close parenthesis.  If everything matches, you’ll end up back at zero at the end!  If not, you may need to figure out where you’re missing a parenthesis.
  • Spelling: If you misspell a word, it won’t work!  So paying attention to spelling is important.
  • Capitalization:  Whether words are capitalized or not matters!  So, for example, red works fine as a color, but Red doesn’t work!  We talked about the convention of capitalizing new words inside a variable name, even through the variable name starts in lower case, like in circleSolid.  That has a name: “camel case”… because it’s sort of like upper-case or lower-case, except it has a hump in the middle.
  • Spaces: Most of the time, you can put spaces in your program however you like: but they often do need to be there!  You can’t run together numbers or variable names and expect it to work.  A lot of programmers like to use spaces to line things up in nice columns, too.

Here’s our whiteboard at the end of this part:

Paying attention to details like this is very important, and will help a lot as you get more experience with writing programs.

Things Other People Said

We finished up today by reading some quotations by famous people about computer programming, talking about, and did some laughing, too.

Any fool can write programs that a computer can understand.  Good programmers write code that humans can understand.

- Martin Fowler

This is talking about the importance of being a good communicator, which was one of the points above.

Controlling complexity is the essence of computer programming.

- Brian Kernighan

Brian Kernighan was one of two people who invented C, one of the most popular programming languages in the world.  He’s talking here about the important of organization, and of hiding unnecessary details, so that you can build programs without being overwhelmed by how complicated everything gets!  In fact, he says that’s the most important thing about computer programming.

Any sufficiently advanced bug is indistinguishable from a feature.

- Rich Kulawiec

Remember a “bug” is a mistake in your program.  A “feature” is something it does, and is supposed to do.  I threw this quotation in for Sophia, because on the first day of class, she found a bug in my web site where you could stretch a solid circle and it would accidentally leave a hole in the middle, and she used it to make a mouth as part of her first program.  But then the next day, I fixed the bug and broke her program!  That’s definitely a bug that turned into a feature.

If you’re about to add a comment, ask yourself, “How can I improve the code so that this comment isn’t needed?”

- Steve McConnell

This is a great concept!  We talked about using comments to explain what’s happening in your programs: but what’s even better than having a comment is organizing your program so that it’s obvious what you’re doing, and you don’t need the comment any more.  This certainly doesn’t mean never write comments: it just means see if you can keep things simple so there’s not as much to explain.

Great software, likewise, requires a fanatical devotion to beauty.  If you look inside good software, you find that the parts no one is ever supposed to see are beautiful, too.  I’m not claiming I write great software, but I know that when it comes to code, I behave in a way that would make me eligible for prescription drugs if I approached everyday life the same way.  It drives me crazy to see code that’s badly indented, or that uses ugly variable names.

- Paul Graham

This is Paul Graham being funny, but also making a very good point.  This touches on the first and last points of advice earlier.

There are two ways of writing computer programs: One way is to make it so simple that there are obviously no mistakes.  The other way is to make it so complicated that there are no obvious mistakes.

- C.A.R. Hoare (sort of)

The last one is actually slightly misquoted.  I didn’t correct it because the original version means nearly the same thing but uses more technical language.

Your Assignment

Your assignment is to clean up your computer program!  Imagine that you’re going to share with other people not just the picture it draws, but the computer program itself.  Get it as clean and nice looking as you can: try to break things down in logical ways, pick really good names, fix all the details, and communicate well to people reading your code.

See you next week!

Follow

Get every new post delivered to your Inbox.

Join 62 other followers