Lab 2
1 Crucial Tips on using Dr  Racket, part 1
1.1 Help!
1.2 Highlighting by holding Shift
1.3 Cutting and Pasting using keystrokes
1.4 Paren Matching
1.5 Moving by s-expressions
1.6 Highlighting using s-expressions
1.7 Auto-tabbing
1.8 Automatic Parens
2 Selecting with the Mouse
3 Programming Exercises
8.9.900

Lab 2

1 Crucial Tips on using DrRacket, part 1

1.1 Help!

DrRacket has built-in documentation on every function you’ll be using. To access it, put the cursor on an identifier and hit F1. Or choose Help|Help Desk. This documentation is local, and should work fine even without network.

You can also find this documentation online at https://docs.racket-lang.org/, though that source won’t include all of your locally-installed documentation, and it’s obviously not available when you don’t have network.

1.2 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.

I know, you’re not suprised. That’s okay. Unless you were. That’s okay, too!

1.3 Cutting and Pasting using keystrokes

You can use cmd-x or ctrl-x (by platform) and cmd-v or ctrl-v (by platform) to copy and paste. Don’t use the mouse.

Yep, we’re still in Notepad territory.

1.4 Paren Matching

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.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 racket
 
(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 Auto-tabbing

Like any other sane editor, DrRacket can indent code for you. When a block of code is highlighted, you can hit <tab> to reindent that block.

Okay, time for a simple exercise.

Here’s a piece of code.

(define (show-example b)
           (begin
 (printf "magnitude of sum of elements: ~s\n"
                  (array-map magnitude (array-axis-fold (my-fft b) 0 + 0)))
 
(printf "sum of magnitude of elements: ~s\n"
        (array-axis-fold (array-map magnitude (my-fft b)) 0 + 0))
 
                 (plot (points (in-array (array->plottable (my-fft b))))
#:y-max 1500
#:x-max 1024
  #:height 300)))

Use the s-expression highlighting keys to highlight just the first printf. Hit <tab>. Note that the printf is now aligned relative to the line before it, but nothing else has changed.

Now, use the s-expression-highlighting keys to highlight the whole function definition. (Not the mouse! Please!) Hit <tab>. See that the whole thing gets re-indented all at once.

Sometimes, you’ll notice that things don’t go where you expect, when you re-indent. This is usually a sign that you have an extra or missing parenthesis, somewhere.

Next simple exercise:

Use the s-expression highlighting expressions to highlight the first printf. Use cmd-x and cmd-v to cut it and paste it outside of the show-example function.

1.8 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 Selecting with the Mouse

Yes, you can select text with the mouse.

Don’t do it.

You’ll miss parens, and wind up scrambling to fix them. If it takes you a minute to find and fix a paren-matching error caused by a mouse selection, and you do this twenty times an hour, you’ve now wasted a third of your development time. Remember, my goal is to get you out of here and doing other things as quickly as possible.

3 Programming Exercises

These exercises are focused on Lists. In this class, the term "List" will be synonymous with "Linked List", or, if you prefer, "Singly Linked List". The best introduction to lists is probably Sections 8, 9, and 10 of How to Design Programs. Read them carefully; they introduces lists carefully, and goes over the design recipe for functions on lists. There are many short-cuts and elaborations on lists that we’ll be using, but this text presents the bedrock truth of linked lists in a way that’s hard to beat.

  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 types, purpose statement, and test cases.

    For this problem only, make sure to leave a complete commented-out copy of the list template in the body of the function. Comment it out using "hash-semicolon".

  2. Figure out how to use :print-type to print the types associated with values. What type does rev-str-app have? Does this make sense? What about the type of ’+’? Why is it so long? Write your answers in the form of a comment.

  3. Develop a representation for bicycles; A bicycle can be either a Trek, a Bianchi, or a Gunnar. Each one has a single field that is a number. I don’t care what the single field of each kind bicycle is called. Actually, I don’t care whether they have fields or not, but experience shows that constructors with no arguments along with higher-order procedures confuse the heck out of students just getting used to Racket. If this doesn’t make sense to you, just take my advice and make up a field for each one. How about num-wheels? Define these using a define-type and a set of structs.

  4. Note! After defining a structure named s1 with fields f1 and f2, you will be able to use the function s1? to determine whether a given value is a structure created with s1, as well as being able to use s1-f1 to get the contents of field f1 and s1-f2 to get the contents of field f2. This will be useful later....

  5. Develop the function only-treks, that consumes a list of bicycles and returns a list containing only the Treks. Hint: it’s fine to use a match as part of the list template, but don’t use a match to determine what kind of bicycle you have; this will impair the abstraction that’s supposed to happen two problems in the future. (Also, don’t use the built-in filter function; the idea of this lab is to give you practice in writing recursive functions on lists. Unless you re-implement filter. Then it’s fine.)

  6. Develop the function only-bianchis, that consumes a list of bicycles and returns a list containing only the Bianchis. Hint: same hint as last time.

  7. Abstract over the two of these to obtain the function onlyThese, that consumes a list of bicycles and a particular bicycle predicatePredicate: a function that accepts any value and returns a boolean, used to represent a set or property. For instance, an even? function or Java’s isOrdered. f (e.g., Gunnar?, or maybe a function that always returns false) and returns a list of bicycles containing only those elements of the list that satisfy f. (Note: you’re passing the function Gunnar? here. If this doesn’t make sense, ask for help!

    Hint: use (Listof Bicycle) as the return type of onlyThese.

  8. Develop the my-append function that consumes two lists and returns the result of appending the second one to the first. So, if called with the list '(a b c) and the list '(d e f), it would return '(a b c d e f). (Don’t use the built-in append function, please.)

  9. Develop the my-take function that consumes a list and a number n and returns the first n elements of the list. If the list contains fewer than n elements, it returns the entire list. (Again, don’t use take, or reverse, or drop, etc. etc.)