Originally authored by Dara Monasch
In the event that you're just joining in, here's a guide to the rest of this series:
Week 5 was an interesting mix of things I’ve learned in other programming classes/languages, and a strange bit of new items. We learned about Arbitrary Sized Data, as well as working off of a list. I apologize for the delay in posting this week, but I was off in Bermuda on vacation, so I wasn’t doing much work. ;)
Lesson 1: Intro to Arbitrary Sized Data
The data we’ve been working with up until now in the course has been of a FIXED size. Arbitrary sized data represents data that is of an unknown amount, or something we just don’t know up front when we’re creating the program or function.
Lesson 2: List Mechanisms
The biggest question I had when we started talking about another data type was… how are we going to represent THIS one? The answer is that while you can use a compound data definition to represent arbitrary sized data, it is much easier to use… a list!
In Dr. Racket, Lists are a primitive data type, in which “empty” is an empty list of anything. An example of this would be: (cons empty). For a list of one element, you would see (cons “Flames” empty), where “Flames” is the first element, and the rest of the list is empty. For a list of two elements, we would see (cons “Leaves” (cons “Flames” empty)) where Leaves would be the first element, flames the second, and the rest of the list would remain empty.
This format of writing lists is referred to as “cons notation” where list values are formed ONLY of values, not expressions. These values can be strings, images, numbers, naturals, anything EXCEPT an expression.
The next question I would have, and I’m sure you do too, is how do you name your list?
It’s pretty intuitive, and you express it simply, as follows: (define List1 (cons “Flames” empty)).
Ok, so great. We can make these thrilling lists of arbitrary size… but how do we access the data once the list is created? Again, pretty easy and intuitive!
(first List1) will give you the first item in your list
(rest List1) will give you the rest of your list
That’s all you need, right? … ok, ok, maybe you want to get the “rest” of the items separately? Perhaps? That’s a bit more convoluted, unfortunately. Here goes…
(first (rest List1)) will give you the second element in the list
(first (rest (rest List1))) will give you the third element
And so on and so forth.
You can also check if your list is empty with the following Boolean expression:
Lesson 3: A First List Data Definition
In order to iterate through arbitrary long lists, it’s important to understand the idea of recursion, or in this case, as the course presents it, “self-reference.” What frustrates me in this lesson of Introduction to Systematic Programming, is that there is, in essence, no explanation of recursion or why it works, it’s just said multiple times to “trust the self-reference”. That’s very difficult for me to swallow because I don’t believe in working that way, but that’s all we’re given here, so that’s what I’m going to have to go with. Here’s an example of a self-reference List definition in Dr. Racket:
;;ListOfString is one of:
;; empty (this is the base case)
;; (cons String ListOfString)
;; interp. as a list of strings
(define LOS1 empty)
(define LOS2 (cons “McGill” empty))
#; (define fn-for-los los)
(cons [(empty? los) (…)))
… (first los) ;string
(fn-for-los (rest los))])) ;ListOfString (you’re “trusting the self-reference” here)
Aaannnnddd that’s all you get from Lesson 3!
Lesson 4: A First Function Operating on List
Please follow along with this as a continuation with the ListOfString Example from Lesson 3
;;ListOfString -> Boolean
;;produces true if los includes “UBC”
(define (contains-ubc? Los) false) ;stub
(check-expect (contains-ubc? Empty) false)
(check-expect (contains-ubc? (cons “McGill” empty)) false)
(check-expect (contains-ubc? (cons “UBC” empty) true)
(check-expect (contains-ubc? (cons “McGill” (cons “UBC” empty))) true)
It’s important to note that the check-expects for this half-explained function check the base case of the list, which is empty, another false case, a case in which the FIRST value is true, and also one in which the true value is embedded within other values in the list.
Lesson 5: Revising the Recipe for Lists
This lesson is really a compilation of quick tips relating to lists, so we’ll treat it as such here for clarity’s sake…
- Arbitrary is NOT random, it simply means the amount is unknown at the onset of program creation.
- Self-reference is necessary in order to review arbitrary amounts
- You also must need a base case, which is detailed on the “data definitions” page for Lists
- Examples should include your base case, and your self-reference cases, as I mentioned in the last lesson.
- When writing your template rules, the appropriate addition when using a list is “self-reference (rest los) is ListOfString”, as a general example.
- Again, it’s reiterated about 43 times in this lesson to simply “TRUST THE NATURAL RECURSION”. So… do that.
Lesson 6: Designing with Lists
This lesson walks the class through an example pattern for working through lists, aka, a practice problem!
ListOfNumber is one of
- (cons Number ListOfNumber)
;;interp. Each # as an owl weight in oz
(define (LON1 empty)
(define LON2 (cons 60 (cons 42 empty)))
#; (define fn-for-lon lon)
[cons [(empty? lon)(…)]
(fn-for-lon rest lon))]))
- One of 2 cases
- Atomic distinct: empty
- Compound: (cons Number ListOfNumber)
- Self-reference: (rest lon) is ListOfNumber
;;ListofNumber -> Number
;;produce sum (weight of owls) in a consumed list
(check-expect (sum empty) 0)
(check-expect (sum (cons 60 empty)) (+60 0))
(check-expect (sum (cons 60 (cons 42 empty) (+ 60 (+ 42 0)))
When you’re working with the natural self-reference, a tip that’s given at this point is to “think about what to do with the RESULT of the natural recursion, not the rest of this list”. In this way, you can kind of blind yourself to how the recursion works, and simply focus on what to do with the result it produces. Again, I don’t really like or agree with this method of teaching recursion, but I suppose it serves its purpose here.
Lesson 7: Position in List Templates
This lesson solely exists in order to provide the following table that you can use to compute the results or holes in your recursive functions.
Contribution of First
Lesson 8: The Reference Rule Part 1
Arbitrary data allows us to handle data that has different kinds of related parts… as with two data definitions. What does this mean? It means that not only can you have primitive items as your list elements, you can also have structs, which hold more than one value within them. This is understood as a “reference relationship”, which refers to a non-primitive data type, which is defined *within the program*. You can utilize these data types with reference: (first los). This produces a “natural helper”.
Lesson 9: The Reference Rule Part 2
This lesson was a short example on why it’s important to create your examples before your data definitions. The reasoning behind this is that your examples will help you write your functions and data definitions more quickly and easily!
Lesson 10: The Reference Rule Part 3
This lesson delves deeper into the idea of a natural helper. Natural helpers in your templates mean that you should take the complicated portion of the function you’re creating, and move it to a separate, helper function. That’s it! The main point here is… make things less complicated, not more!
Lesson 11: Natural Numbers
Did you know that there are an arbitrary number of natural numbers? Yeah, I never thought about that either, but it’s true!
This means that you can….
add1 - which is a function that takes a natural number and adds 1 to it
sub1 - which is a function that takes a natural number and takes one from it
Basically you can step up or down with natural numbers, using these simple functions, without having to write your own!
Week 5 Summary
This week truly isn’t so bad. The worst part is the fake learning of recursion, which, while it annoys me, it’s not so difficult the way it’s being presented here. We’re learning to make lists of things and traverse/access them, which, truly, is very useful!