1 Crucial Tips on using Dr Racket, part 1
1.1 Source position information
1.2 Paren Matching
1.3 Highlighting by holding Shift
1.4 Cutting and Pasting using keystrokes
1.5 Moving by s-expressions
1.6 Highlighting using s-expressions
1.7 Automatic Parens
2 Lab 2 exercises

Lab 2

1 Crucial Tips on using DrRacket, part 1

1.1 Source position information

Does a test case of yours cause an error? In this case you’ll get MUCH better information from DrRacket if you lift the offending expression out of the test expression.

Type this code:

#lang plai
(define (my-fun a b)
  (+ (a) (b)))
 
(test (my-fun 3 4) 16)

... and you get back an error like this:

(exception (my-fun 3 4) "procedure application: expected procedure, given: 3
(no arguments)" "at line 4")

Unfortunately, the test form is obscuring the helpful information that DrRacket can show you. To see a bunch more helpful information, make a new copy of the expression that caused the error, so now your test code looks (temporarily) like this:

#lang plai
(define (my-fun a b)
  (+ (a) (b)))
 
(my-fun 3 4)
(test (my-fun 3 4) 16)

... and run it again. Voila! Error location highlighting, and lots of other useful information.

1.2 Paren Matching

The first few of these are things that you probably already knew, but I want to make sure.

When the cursor is outside of a parenthesis, the matching pair of parentheses are highlighted, along with everything inside. You knew that already, right?

1.3 Highlighting by holding Shift

When you hold down shift while pressing cursor movement keys, the intervening characters are selected. Try putting the cursor somewhere in your code, and holding shift-down.

1.4 Cutting and Pasting using keystrokes

You can use cmd-x and cmd-v to copy and paste. Don’t use the mouse.

1.5 Moving by s-expressions

You may have noticed that there are a lot of parentheses in Racket. It turns out that this can be a blessing, as well as a curse. By using <option>-left and <option>-right, you can move the cursor by a matched set of parentheses or datum, also known as an "s-expression". So, for instance, if your cursor is at the beginning of the program, you can use <option>-right twice to move down by two full expressions.

#lang plai
 
(define (f x)
  (* (- (* x x)) (+ x 9) 4))
 
(define (g x)
  (* x x 5))

Use <option>-left and <option>-right to move back and forth through the top-level expressions.

Then, use <option>-left and <option>-right to move back and forth through the arguments to the first * in the definition of x.

The <option>-up combination is also extremely useful; it moves the cursor to the outside of the enclosing expression. Using <option>-up rather than the simple arrow keys means that you’re always in a position to highlight or cut the given s-expression. Also, popping to the outside of a long function with two or three <option>-up’s is much faster than hitting the up key a whole bunch of times.

1.6 Highlighting using s-expressions

You can combine the last two subsections; by holding <shift> while using <option>-left and <option>-right, you can highlight one or more s-expressions. This is most useful when you’re planning to cut them, or replace them (or wrap them in parens... but we’re not there yet).

1.7 Automatic Parens

Okay, here’s where the magic gets better. In the Preferences > Editing > General box, check the "Enable Automatic Parentheses" option.

Now, something strange happens; when you type a left-paren ’(’, you’ll see a matching pair of parentheses appear, with the cursor in the middle.

It’s nice not to have to type the closing parenthesis, but it’s even nicer that when you use this binding, your parentheses are never unbalanced.

But wait! What if you want to wrap parentheses around a set of existing expressions? No problem. Just highlight them, using the keystrokes we’ve already described, and then type the left paren. You’ll see a pair of parentheses, wrapped around the highlighted expressions.

The same keystrokes also work for the square bracket, ’[’.

There’s even more in this space, but I think we’d better stop here for a bit.

Here’s a simple exercise; you should be able to complete this without having unbalanced parentheses.

In the following code, change the "if" into a cond. First, change the keyword "if" into "cond". Then, highlight the two following expressions, and wrap them with square brackets. Then, highlight the third one, beginning "append", and wrap it with square brackets, and insert the word "else" following the open bracket. Done!

(define (srl:map-append func lst)
  (if (null? lst)
      lst
      (append (func (car lst))
              (srl:map-append func (cdr lst)))))

2 Lab 2 exercises

  1. Develop the function rev-str-app, that accepts a list of strings and returns a single string combining the input strings in reverse order. Use string-append to join strings. So, calling the function with the list containing the strings "ball", "juice", and "frog" would produce the string "frogjuiceball". Follow the design recipe, including contract, purpose statement, and test cases

  2. define a piece of compound data to represent desks, which are a kind of office furniture. A desk has a width, a height, and a depth. Provide an example.

  3. extend the definition of office furniture to include Bookshelves. A bookshelf has a depth, a number of shelves, and a shelf-width. Provide an example