Follow-up On Simply Scheme Chapter 1 Notes

Learning Methodology Problems from Chapter 1 Notes

  • Lack of trees.
  • Lack of explicitly writing down enough questions.
    • Need to take every part of the program seriously – everything is there for a reason, presumably. What is the reason?
  • Lack of going step-by-step enough (did this somewhat but could do better).
  • Not taking advantage of the interactivity of the interactions window of DrRacket enough. Need to play with things more!
  • Moving forward while still being fuzzy on stuff.
  • Trying to go through stuff too quickly.

Things to focus on improving for this post:
1. Go step by step more
2. Test stuff more
3. Make a tree

Going More Step by Step on the Ice Cream Choices Example

Got stuck in my attempt to understand this one, so seemed worth doubling back.

If Statements

This procedure has an if statement. Can I actually write one of those on my own? Let me try it (using an expression from Roman history)

Here are some very simple examples of if from a Scheme guide which I’m bookmarking now 🙂:

it also describes the general form of the syntax:

Note that you don’t need to expressly introduce the alternative with an else or something like that.

Let me make my own if statement.

It actually took me a couple tries to get the syntax and parentheses correct. Probably a strong indicator that testing my understanding of writing if in Scheme was a good idea!

I get the expected output from this.

Let Contrasted with Define & Lambda

Earlier I said:

I got a little confused trying to figure out what let does and how it’s different than lambda. I don’t wanna get stuck in the mud by jumping the gun (intentional mixed metaphor 😉 ) so I won’t worry too much about this for now. It seems like let is kind of similar to lambda, except with lambda you don’t give the temporary function a name and with let you can (or have to? Not sure).

I found this article which contrasts let and define and I found the comparison helpful.

Following the advice on that page, I first used define in the interactions window.
Here’s what they showed should happen:

And here’s what happened for me:

Pretty close! I’m missing the line with #<unspecified> and just have a blank line there instead.

The article says

This shows that even once used, the variable x continues to exist, it is defined for all to see, use and (as we shall see later on) modify at will.

The value of the x as 2 persists once it is defined as 2.

They contrast let with this:

If I enter the following statement in the interactions window:

I get 8

But if I try to get the value of x again:

Notice here, how once the block of code has finished executing, the variables x and y are no longer accessible.

You also can’t just define something in a let and return the value.

let expects a procedure. If you evaluate (+) by itself, it returns zero, and so if you use it with just one number, it returns that number. So if we did want to just get the same value x value out of let for some reason in the above example, we could do:

Which gives us 2. I don’t know why one might want to do such a thing, but it could be done.

The article also contrasts the general form of the two expressions let and define:

In general, the form of a define statement for a variable is as follows:
(define <variable name> <variable value>)

In general, the form of a let statement is as follows:
(let ((var1 val1) ... (varn valn)) (<body>))

With let, you actually use the variables to perform some operation immediately and then the values of the variables are no longer available. Given that, it makes sense that you would have to say what that operation is immediately within the let statement. Whereas with define, because the assignment of a value to a variable persists, we can assign some variable a value and then use it whenever later on.

In my last post I said:

It seems like let is kind of similar to lambda, except with lambda you don’t give the temporary function a name and with let you can (or have to? Not sure).

With let, it does look like you have to assign something a value and then do something with it.

I was thinking of the difference between let, lambda, and define, and how to try to put the difference in an easy-to-grasp way. If this isn’t quite right then hopefully someone will say it’s wrong and I can correct it 🙂

With define, you give some value to a name and use it to do stuff later on. The value could be a word, a number, or a function. And you can refer back to that value with the name you gave it later cuz you’ve defined it in a lasting way.

With let, you give some name to a value in order to do stuff right now. You do your stuff within the let expression.

With lambda, you skip the whole naming part and just start immediately doing stuff (though you do have to specify what you’ll be doing stuff to.)

Map

In my previous post I said:

every applies a function that follows it to each word in a sentence. map applies a function that follows it to each item in a list.

Let’s see what this actually means in practice with a simple example.

This returns (5).

This returns '(5 7). This is the behavior I would expect so far.

Reduce

In my previous post I said:

reduce is similar to the accumulate function used in the Acronyms example. Accumulate “takes a procedure and a sentence as its arguments. It applies that procedure to two of the words of the sentence.” Chapter 17 of Simply Scheme says that “Reduce is just like accumulate except that it works only on lists, not on words.”

Therefore…

…returns 26, unsurprisingly.

and this:

returns 'lalalala. Note that if you just give (la la la la) to word, it does not work, because word doesn’t expect a list.

So you really need the reduce here.

Append

As I said in my last post, append append makes a list out of the elements of lists provided as arguments.

So:

produces '(New York New Jersey Connecticut) in a single, flattened list with no nested list structure.

What if the lists you are trying to append are double-nested?

this produces
'((New York) (New Jersey) (Connecticut)), where the elements are in a single list, but within that list, they are only nested once.

Car & Cdr

car selects the first element of a list. So for (car '(New York New Jersey Connecticut)) it returns 'New and for (car '((New York)(New Jersey)(Connecticut)))  it returns '(New York).

cdr selects all but the first elements in a list. So for (cdr '(New York New Jersey Connecticut)) it returns '(York New Jersey Connecticut) and for (cdr '((New York)(New Jersey)(Connecticut))) it returns '((New Jersey) (Connecticut)), as I would expect.

What happens if you cdr a list with only one element? For example, what happens when you cdr a list with only nested list?

You get an empty list.

Lambda

I think I should play around with lambda a bit more as well.

If we just do:

We get back a procedure object.

That’s because we haven’t actually applied the procedure to anything yet. If we want to actually apply the procedure to something, we need to give it some input to serve as the number:

Note the highlighting:

So what we’re doing in the above is generating our procedure object (with the lambda in the highlighted part), and them giving Scheme something to apply that object to (the 3).

Prepend-every – Combining Map & Lambda

Now I’ll start trying to combine the different parts I’ve talked about to build up to a larger procedure.

First let’s try map and lambda. Part of the choices program draws upon a helper function prepend-every, which uses map and lambda, so that seems like a good test case.

I talked about prepend-every a bit in my last post.

I saw that it prepends an item to each element of a list. For example:

So how does this function work, in detail?

Let’s look at a different version of the function first.

prepend-every-nomap has had the map removed and the parentheses adjusted accordingly. What value will this give us when we run it?

So rather than prepend apple to each element of the list, it prepends apple to the whole list. Why?

map is the thing in the original prepend-every procedure that tells the lambda of prepend-every to access each element of the list lst. Without map providing this instruction, prepend-every-nomap just treats the entire list lst as one unit and runs the lambda procedure on it. The lambda procedure takes the item and the lst and makes a sentence out of them. In the original prepend-every, I think that choice stands for the individual element of a list being selected at that moment by map for combination with the item in the lambda function. But in prepend-every-nomap, choice brings in the entire lst.

All this shows the role of map in the prepend-every function and how it can operate together with lambda. map can enable a lambda function to do a whole lot more than it might be able to otherwise.

Putting Things Together

I made a version of the choices procedure with print statements for smaller and menu (and newlines to clean things up) in order to get a better idea of what was going on:

I ran the above with (choices '((vanilla chocolate)(cone cup)(small large))) as the input and got the following back:

So here is my attempt to explain this:

  • When the number of nested lists being provided as the menu gets down to 1, then when the (let ((smaller (choices (cdr menu)))) line tries to get the cdr of that menu, it will not return an entry but an empty list, as described in the Car & Cdr section above. We actually specify that the program return a nested empty list on (null? menu) and not just an empty list. I’m not 100% on the reasoning for that.
  • When we get to the point where (cdr menu) returns our empty nested list, we still have an entry in our menu list – in my example, we have '(small large). So I think what happens is that when we get down to the base case, smaller is an empty nested list (()). Then we go through the (map (lambda (item) (prepend-every item smaller))(car menu)))))) part of the program. The map goes through each element of (small large) – so small and large respectively – and applies the lambda function. The lambda function takes small as an item and then prepends small to the empty nested list that the let has given the name smaller. The lambda function then goes through next item provided by map, large, and does the same, prepending it to an empty nested list. The result of this process is this line:
  • The format of '((small) (large)) poses somewhat of a problem, because we’re not done processing the information from our choices list at this stage. We need to use the information from '((small) (large)) at a “higher level” of the sequence of recursive calls that the choices procedure makes. But here we run into a problem. I tried to demonstrate the problem by removing the reduce from the program full choices program:

  • So what exactly is going on here? prepend-every operates by combining some item with a list using the sentence-former se. Without reduce and append working together to flatten the structure of the lists generated by the running of the choices procedure, prepend-every ultimately winds up getting handed a nested list, ((small)), which it doesn’t know what to do with. reduce append serves to keep the lists from getting so nested that they cause a problem for prepend-every. This allows the program to function as a whole and generate our desired result.

Questions

  1. Is there a reason that we have the return on (null? menu) be a nested list? There must be, because if you change it to just an empty list, the program returns an empty list.

Learning Methodology Review

I accomplished the goals I wanted to in terms of learning methodology. I went step by step, tested out lots of stuff, and made a tree. I found the step by step and testing stuff out things very helpful. In particular, I think I made some gains in the skill of figuring out how to test stuff, which seems important. I think the print statements I used in the “Putting Things Together” section are a good example of this.

I also made a tree. I am not sure how much the tree helped. I think maybe it helped a bit with understanding the structure of the program, but I think testing out the individual parts of the program helped way more with that.

Tree

Here is my attempt at a tree for the choices procedure.

Simply Scheme Chapter 1 Notes

I’ve done some exercises in Simply Scheme a couple times previously. I figured I would try to go through it in a more thorough, careful and documented way while keeping in mind the lessons I learned from my recent Peikoff Grammar Course project. My work will be posted at a Github repository.

Goals

  1. Practice overall learning methodology stuff like writing thorough explanations, brainstorming, using trees, and going step by step.
  2. Review previous learning efforts of mine, along with other people’s learning efforts, and compare and contrast, reflecting on differences, mistakes I made, things I can do better, etc.
  3. Gain some subject-matter specific knowledge I can build on for later learning efforts and ultimately for some specific projects that I’d like to work on.
  4. Avoid getting stuck, and work on quickly and successfully getting unstuck if I do get stuck.

Avoiding Getting Stuck

Avoiding getting stuck warrants some more discussion, since that’s been a big issue for me in prior learning efforts.

I found the general principle described in this article of Elliot’s to be quite helpful. I don’t think I’ve perfectly applied it, but it’s something my mind turns to when I really feel like I’m stuck and spinning my wheels.

Another thing that’s helped with getting unstuck is paying attention to how much I am writing. As a rough approximation, if I am regularly writing something while working on stuff, things are going okay. In the worst case, if I am writing stuff and I have a misconception, then I am providing more detail about my misconceptions and so am making it easy for either myself or others to see the misconceptions. And if I am actually on the right track, then writing means I’m working my way (however slowly) towards some sort of conceptual clarity. I think some sort of measure or indicator of making progress like this is important. It’s not perfect, but if you notice that your word count hasn’t moved for a while, that’s at least a potential alarm bell to indicate to you that something is going wrong. So between paying attention to amount of time I’ve spent thinking about something, and paying attention to how many words I’ve written, that’s two potential alarm bells I have for the issue of getting stuck.

I think the getting stuck issue has an aspect to it that involves a misconception around what problem solving is supposed to be like. I think of it as a sort of romantic misconception (in the broader and the sexual/relationship sense of that term) where the solution to a problem comes to you in a sudden flash of inspiration. This is connected with certain ideas people have about genius. I think the truth is that a lot of what people consider genius consists of having certain traits in a thorough way. Some traits that I think are important:
– being organized and systematic in what you do.
– being honest about what you know and don’t know
– seeking out and being open to criticism about what you are doing.
– being intellectually curious about what you are working on.
There are also bad traits you need to avoid, like being disorganized, dishonest, hostile to criticism, and passive.

Getting DrRacket Set Up

Before doing anything else, I need to get DrRacket set up on my Mac, and figure out how to load a definitions file that will let me do the exercises effectively. I already DrRacket installed, so the main thing was loading a definitions file.This file from github seems to do the job. I googled for the appropriate way to get started and tried a few different things. Initially, I was trying to use the definitions file from github and getting an error message about a bad relative path in DrRacket. I figured out that the file paths seem to be relative around the current file I am working in. I made a test file called “test.rkt”, made a subdirectory called “definitions” (since the file from github defines a bunch of procedures) and put the file from github into it. In test.rkt, I entered the following into the definitions window (which is the top part of the interface)

I then ran this, and:


🙂

Testing a Simply Scheme procedure:

Hmm. I think the output is not supposed to have an apostrophe like that, based on this chapter: https://people.eecs.berkeley.edu/~bh/ssch5/words.html

I tried a couple of Simply Scheme packages available for download through the DrRacket manager and they had similar behavior as far as apostrophe. I think I won’t worry about the apostrophe for now unless it causes an issue. I’ll use the github simply scheme file for now.

Quotes in a given section come from the chapter of Simply Scheme in question unless otherwise specified.

Some DrRacket macOS Keyboard Shortcuts

In the interactions window, esc + p for previous command entered, and hit esc + n for next command. Seems like you need to hit escape each time – you can’t just hold down escape and hit p or n to cycle through recent commands.

ctrl + left or right arrow to move forward or back a line, respectively.

esc-backspace to delete a word.

Getting Github Set Up

I made a Github repository for my Simply Scheme work.

I already had the Github Desktop App set up on my Mac. I just needed to make a New Repository for Simply Scheme and then put the files I’m making in that repository.

Github Desktop shows you changes that have been made to your files and which files have been changed.


You have to provide a brief summary of your changes before you can hit the Commit button.

And then you have to push the changes for them to get published to the web.

Using the Fallible Ideas List Discussion

There have been lots of posts on the Fallible Ideas list (mostly by AnneB) about Simply Scheme. I intend to refer to these as I work my way through the course. I set up a Smart Mailbox in MailMate to help me keep the relevant posts handy

Reviewing Past Work

Since I’ve tried working through this book previously, I will be referring to what I’ve done previously and comparing that to what I am doing now. I’ll do this at the end of each chapter.

Part I of Simply Scheme

Note that since I’ve gone through some of the course before, I know that sentences are lists, what some basic functions do, and various other details. So sometimes I may refer to things in light of context that I already have but that I may not have introduced in my notes.

Introduction: Functions

Our goal is not for you to feel that you could re-create these programs, but rather that you get a sense of what kinds of programs we’ll be working with.

Minor grammar issue here (I’m trying to actively notice things in order to keep my grammar skills sharp): this sentence should be “but rather [for] you [to] get a sense” to maintain parallelism.

Chapter 1 – Showing Off Scheme

Quotes in this section come from this chapter unless otherwise specified.

Procedure syntax – The parentheses are syntax for indicating to Scheme that we’re calling a procedure. The ' is important too (indicates string IIRC).

Primitive procedures: procedures Scheme already knows.

Compound procedures: procedures we define.

Example: Acronyms

I ran the following code on some example inputs:

So basically (starting from the inside and working my way out), (every first phrase)) applies first to every word of phrase, getting the first letter of each word in the phrase. accumulate word accumulates the letters produced by that process into a word. word tells accumulate what to do – accumulate can do different things, like add up a bunch of numbers if you tell it to + or find the highest number in some list of numbers if you tell it to max.

Simply Scheme says:

Accumulate takes a procedure and a sentence as its arguments. It applies that procedure to two of the words of the sentence. Then it applies the procedure to the result we got back and another element of the sentence, and so on. It ends when it’s combined all the words of the sentence into a single result.

So every first phrase grabs the first letter of each word in the phrase. So suppose the phrase is (make america great again). every first phrase will spit out (m a g a) from that.

Then accumulate word puts the first two letters together, and then takes those first two letters and adds the third letter, and then takes the now three-letter word and adds the fourth letter.

I wanted to show what was going in detail in DrRacket. I ran into the issue that if you try to use trace on some things like word, it gives an error and won’t run. I got the idea from a stackoverflow comment that I could define an alias for the name of function I want to trace, use the alias in place of the original function, and run trace on that.

So by writing this

I was able to get this output:

So that follows what I expected re: how word operates, with the exception that it seems to be starting from the end of the phrase rather than the beginning.

The output was different between some examples in a way that I thought was interesting:

Note that the capitalization is respected and, more interestingly, that the output has “quotation” marks around it if any of the letters are capitalized.

It looks like capital has to be in one of the first letters of each word (the letters that make it into the acronym) for the output to get the quotes. Otherwise, the output just goes back to the apostrophe. I’m not sure why the output has this variation.

Did you have trouble figuring out what all the pieces do in the acronym procedure?

I think that the procedure goes through each word in a list of words that you pass it, and then takes the first letter of each word one and builds a new word out of that, and that becomes the acronym.

Notice that this simple acronym program doesn’t always do exactly what you might expect:

I expected it to do that 🙂

So now I think that the program is checking each word against a list of words defined in (real-word?). The list of words includes some articles and prepositions that we want to treat as not being real words for the purpose of making acronyms. I think (real-word?) works by checking that a word is not a member of the list of not-real worlds. If a word is not a member of the list, it gets included in the acronym. If it is a member, it doesn’t. I forget a lot of details about the exact step-by-step operation (which I expect to refresh myself on shortly) so this is just a high level summary of what’s happening.

Below is some output from running the updated version of the acronym program on some input:

So now it handles that preposition.

This shows that the real-word? function returns a boolean value.

Example: Pig Latin

The Simply Scheme text contains an important note about this expression:

(By the way, if you’ve used other programming languages before, don’t fall into the trap of thinking that each line of the pigl definition is a “statement” and that they are executed one after the other. That’s not how it works in Scheme. The entire thing is a single expression, and what counts is the grouping with parentheses. Starting a new line is no different from a space between words as far as Scheme is concerned. We could have defined pigl on one humongous line and it would mean the same thing. Also, Scheme doesn’t care about how we’ve indented the lines so that subexpressions line up under each other. We do that only to make the program more readable for human beings.)

This note contains some important points:
1) the whole pigl program is a single big expression, not something with different parts that exist on multiple lines.
2) for the purposes of scheme, new lines and spaces are treated the same.
3) scheme does not care about indentation.

The pigl program checks if the first letter of a word is a vowel. If it is, it appends “ay” at the end of the word and returns the word. If not, the program calls itself again on a word consisting of the current word but with the first letter moved to the end. (word (butfirst wd) (first wd)) is the part that moves the first letter to the end.

You’ve seen every before, in the acronym example, but we haven’t told you what it does. Try to guess what Scheme will respond when you type this:

(every pigl '(the ballad of john and yoko))

every applies a function that follows it to each word in a sentence. So every pigl will apply pigl to each word in the sentence above, producing something like ethay alladbay ofay ohnjay anday okoyay. Let’s check:

yep 🙂

Example: Ice Cream Choices

Ok now we’ve gotten to an example that I cannot easily describe the operation of offhand. I remember being a bit fuzzy about map and reduce in particular, and being confused about lambda as well.

Lambda

Chapter 9 describes lambda as

the name of a special form that generates procedures. It takes some information about the function you want to create as arguments and it returns the procedure.

The book says that if you want to add 3 to every number in a list using the tools the book teaches you before it introduces lambda, you have to do something like this:

Every needs a function to apply to stuff, so you need to give it a function. In the above example, you define a helper function “add-three” for the purpose of having a function to use with every.

It’s slightly annoying to have to define a helper procedure add-three just so we can use it as the argument to every. We’re never going to use that procedure again, but we still have to come up with a name for it. We’d like a general way to say “here’s the function I want you to use” without having to give the procedure a name. In other words, we want a general-purpose procedure-generating procedure!

So that’s what lambda is.

Creating a procedure by using lambda is very much like creating one with define, as we’ve done up to this point, except that we don’t specify a name. When we create a procedure with define, we have to indicate the procedure’s name, the names of its arguments (i.e., the formal parameters), and the expression that it computes (its body). With lambda we still provide the last two of these three components.

Here’s an example of lambda:

So a and b are the formal parameters, and then a function is defined which multiplies a by 2 and then takes that product and adds b to it, and then 5 and 6 are provided to the function, and so the result is ((2 x 5) + 6) or 16.

Structure of Programs

I wonder if it’s actually more than “slightly annoying” to have to define a helper procedure in this case. I wonder if breaking out tiny bits of programs you only use once is a bit like having too many commas.

If you don’t have any commas and just go on and on in a long continuous unbroken stream of thought then it becomes overwhelming and that’s too little structure.

On the other hand, if, you have, say, a constant stream, of breaks, in your thoughts, using commas, then, you render the commas, kinda useless, as a structuring device, by virtue, of your, overuse.

My naive guess is that parts of programs should be broken off into a separate part according to criteria like: reaching a certain level of complexity, getting repetitively used a certain amount, and other stuff. And so a part of a program that does a simple thing a grand total of one time is the poster child for what you don’t want to breaking off into a separate function. And so structuring a function in such a way would actually be bad, objectively.

Other Functions in the Example

Let

I got a little confused trying to figure out what let does and how it’s different than lambda. I don’t wanna get stuck in the mud by jumping the gun (intentional mixed metaphor 😉 ) so I won’t worry too much about this for now. It seems like let is kind of similar to lambda, except with lambda you don’t give the temporary function a name and with let you can (or have to? Not sure).

Map

map is similar to every. See this chapter. That chapter describes an important difference between map and every, which is that map preserves nested list structures while every flattens them. every applies a function that follows it to each word in a sentence. map applies a function that follows it to each item in a list.

Reduce

reduce is similar to the accumulate function used in the Acronyms example. Accumulate “takes a procedure and a sentence as its arguments. It applies that procedure to two of the words of the sentence.” Chapter 17 of Simply Scheme says that “Reduce is just like accumulate except that it works only on lists, not on words.”

Append

Append makes a list out of the elements of lists provided as arguments.

car & cdr

car selects the first element of a list, and cdr selects all but the first element. So they’re kind of like first and butfirst.

Looking at Ice Cream Choices Again

This part checks if the “menu” is empty and, if so, returns an empty list:

This let (I think) creates a function named “smaller” that callschoices on all but the first item in the menu:

I got pretty stuck trying to figure out what’s going on with the reduce/append/map/lambda part. It’s a lot of moving parts. I think I’ll just wait on that for now.

Running the Example

If you run the choices program with the following input:

you get:

huzzah 🍦

Example: Combinations from a Set

Here’s a more mathematical example. We want to know all the possible combinations of, let’s say, three things from a list of five possibilities. For example, we want to know all the teams of three people that can be chosen from a group of five people. “Dozy, Beaky, and Tich” counts as the same team as “Beaky, Tich, and Dozy”; the order within a team doesn’t matter.

And if you give this program the following input:

(combinations 3 '(a b c d e))

you get:

So the program is finding all the possible three-letter combinations of the letters a,b,c,d, and e.

The book says:

(If you’re trying to figure out the algorithm despite our warning, here’s a hint: All the combinations of three letters shown above can be divided into two groups. The first group consists of the ones that start with the letter A and contain two more letters; the second group has three letters not including A. The procedure finds these two groups separately and combines them into one. If you want to try to understand all the pieces, try playing with them separately, as we encouraged you to do with the pigl and acronym procedures.)

Let’s try it 🤔

Let’s look at just the prepend-every part

That worked how I expected! The name helped…
It doesn’t work if you try to append a word to just another word. It needs a whole list of words.

So prepend takes a word and appends it to each item in a sentence.

Ok let’s look at other parts of the program.

(cond ((= size 0) '(()))

cond is a special function that lets you specify what to do in a list of alternative situations. I think this first line here basically says that if the size = 0, then you return … well it looks like it’s returning an empty list within a list based on the number of parentheses. Offhand I’m not sure why it would be a list within a list. I think it’s returning something empty. I think it’s returning something empty as part of this program’s handling of the base case though, cuz we see later that the program subtracts 1 from the size at one point:

(combinations (- size 1)

And since this program recursively calls itself, I think that subtraction is something that is going to happen repeatedly, until the number gets to 0.

The other possibility that occurs to me is that the (cond ((= size 0) '(())) line is meant for handling a special case where someone happens to enter 0 initially, but I don’t think that’s the point of it.

The next line I’m going to look at is

((empty? set) '())

So this says that if set is empty, return an empty list.

This gives you an idea of how empty? works.

One part of the program is:

(combinations size (butfirst set))))))

butfirst returns all but the first item in a list:

But if the list only has one value and you call butfirst on it…

…you get an empty list. I think the point of ((empty? set) '()) is to catch when this happens.

So now let’s look at the part highlighted in blue:

(first set) gets the first item in the set (e.g. the letter “a”). prepend-every prepends that item to the result of calling

So let’s think back to (combinations 3 '(a b c d e)). the letter a would be getting prepended to combinations (3 - 1) '(b c d e). So a would be getting prepended to a bunch of 2 letter iterations of b, c, d, and e.

And then in this part of the program:

combinations calls itself with all but the first letter. And so when the resulting list '(b c d e) passes through this call to combinations, then ultimatelyb will wind up getting appended to some 2 letter iterations of c, d, and e, similar to what I describe with a above.

Okay. I think I get the general idea of how it works. Good enough for now anyways.

Example: Factorial

This one is pretty straightforward.

If n = 0 it returns 1, otherwise it multiples the value of n by the result of running factorial (- n 1)) until you get to 1.

Exercises

1.1 Do 20 push-ups.

💪

1.2 Calculate 1000 factorial by hand and see if the computer got the right answer.

No 🙂

1.3 Create a file called acronym.scm containing our acronym program, using the text editor provided for use with your version of Scheme. Load the file into Scheme and run the program. Produce a transcript file called acronym.log, showing your interaction with Scheme as you test the program several times, and print it.

The built-in DrRacket logging function gave me weird output so I just pasted the content of the interactions window into a file.

End of Chapter Review

My Prior Learning Efforts for this Chapter

I couldn’t find any work that I’d done on this chapter previously. I think that’s notable. In light of the amount of stuff I wrote here, it’s actually pretty astonishing.

Other People’s Learning Efforts for this Chapter

AnneB wrote a bunch of posts on this chapter in February of this year. I’m not actually done going through all of them, but I think the amount of effort she put into going step by step, testing things out, and sharing errors she was running into, is really great.

Learning Methodology Review

I did an okay job of writing out my thoughts and thought process for most things.

I didn’t make use of trees. I should work on that.

I got stuck trying to describe part of the ice cream choices example. A tree would have possibly helped. One thing I had an issue with was not being sure the best way to organize such a tree. If I had read through the emails early, I would have seen this tree from AnneB from which I could have drawn some inspiration.

A related thought on getting stuck on stuff – I think getting stuck is bad. On the other hand, I think that only doing exactly what the book tells you at the time that it tells you to do it is also bad. You should have some energy and should try to see how far their reason can carry them in thinking about things, and not need the permission of the book to do so. But if you’re not practiced at making your own judgments about what to try and how long to spend on it, you might waste some time while you figure that out. I don’t have a great solution to this issue at the moment.

Notes on HTML and CSS

I took some notes on HTML and CSS, mostly from some Treehouse videos.

In some cases I just copied their short notes but a lot of the content is my own actual notes/thoughts/screenshots.

Note: some coding-related formatting might not display properly in the email version of this blog post. It should look fine on the website though.

HTML

Basics

Elements

Elements define structure and content of objects within a page. Examples:
– Headings: indicated by <h1> through <h6> tags
– Paragraphs: indicated by <p> tag

HTML element encompasses opening tag, closing tag, content (optional for content-less tags) Eg:

<p>This is the content</p>

This complete thing is called a HTML element.

Tags

HTML tag is just opening or closing entity. For example:

<p> and </p> are called HTML tags

Opening tag marks start of element. Closing tag marks end and has forward slash before element’s name. Content goes between elements.

Self-closing Tags

Some tags are “self-closing”, so you don’t need two sets of tags.

A self-closing tag is a special kind of HTML tag that does not have a closing tag counterpart. These mean that the tag has no content. These include the <link/> and <img/> tags.. According to HTML 5, the closing forward slash is optional.

Attributes

Provide additional information about elements. Examples:
– id: identifies element.
– class: classifies element. Can use for purposes of styling.
– src: specifies a source for embeddable content.
– href: provides hyperlink reference to a linked resource.

Organization of an HTML Page

Everything on a page is inside <html></html> tags except for the doctype declaration.

Head = Behind the scenes info
Body = The stuff that shows up in the browser

One standard organization of the body a web page:
– Header – a container for introductory content or a set of navigational links.
– Main – The main content area consists of content that is directly related to or expands upon the central topic of a document, or the central functionality of an application.
– Footer – typically contains: authorship information; copyright information; contact information; sitemap; back to top links; related documents

CSS

Comments

You create comments by using /* */.
Cmd-forward-slash is often a comment shortcut key for Mac text editors.

Purpose

Lets you make styling/presentation changes en masse by just editing a CSS stylesheet rather than making lots of changes to individual elements of a web page.

Ways of Styling Pages

In-Line

You can actually style stuff in-line e.g. the style attribute in the h1 tag below:

But this is considered bad form and kind of defeats the purpose of using CSS in the first place, since to make changes later you’ll have to edit the actual HTML…

Internal

Internal styles are embedded in the <head>section of the HTML document and are defined inside a <style> tag.

Drawback is that changes you make will only affect that web page.

Both in-line and internal can be useful for testing or very small projects.

Linking an External Stylesheet File

Can style multiple HTML pages with a single sheet with this method.

Can use multiple stylesheets in a single HTML document.

Must link stylesheet in HTML. Best practice is to do this in the <head> tag. And you would do this using something like  <link rel="stylesheet" href="css/style.css">.

Using an @import Statement

This can import the content of another stylesheet into current stylesheet or HTML file. Has to appear before other styles to work properly.

Purpose of Importing

Can make CSS more modular by letting you import different styles. However, more imports means more requests to the web server, and this can affect performance.

Classes

Classes can be used to style only tags with the relevant class attribute rather than every <p> or whatever. You use a . dot before the class name in the css file in order to indicate that you’re styling a class.

Properties

A CSS property is a characteristic (like color) whose associated value defines one aspect of how the browser should display the element.

Selectors

CSS Selectors are what target the tags on a web page for styling purposes.

In the example below, h1 is the selector and the rest (the highlighted portion) is the declaration block.

The structure of the declaration block is a property and a value followed by a semicolon, and with the entire block surrounded by curly brackets. Multiple values can be used inside a declaration block.

Universal Selectors

Universal selector is \*, very powerful, gotta be careful with it, affects every element on a page.

Element/Type Selectors

Type selectors target element types on the page. They’re also called element selectors because we use the element’s HTML tag as the selector.

ID Selector

The ID selector uses the id attribute of an HTML element to select a specific element.

An element can only have one ID at a time.

ids can only be used once. You cannot have more than one element with the same ID in an HTML document.

To select an element with a specific ID for styling in a stylesheet, write a hash (#) character, followed by the ID of the element. E.g. the following will select elements which have the ID primary-content.

Another function of ids is to create landmarks/anchors within a page. E.g. you can give a header the ID top and then link to that ID with a href to #top.

Class Selectors

Class selectors let us target elements based on their class attribute. The main difference between a class and an ID selector is that ids are unique and they’re used to identify one element on the page, whereas a class can target more than one element.

Class selectors use a dot notation:

And you set a class attribute in the html file:

Reusing classes

Class selectors can target multiple elements, as already mentioned. You can also have an element with multiple classes. Example:

Using Class Selectors & ID Selectors Together

You can use both an ID and class on an element. However, the styles define in the ID selector carries more weight than styles defined in classes, cuz ID selectors are more specific.

Descendent Selectors

CSS lets us target elements based on their relationship in the HTML document. We can combine selectors to create descendant selectors that target elements that are descendants of an element. This makes our selectors more specific.

Pseudo-classes

Pseudo-classes are similar to classes, but they’re not explicitly defined in an element’s class attribute. Unlike type, ID and class selectors, pseudo-classes can target elements dynamically based on user interaction, an element’s state, and more.

Per Mozilla Developer’s Network,

A CSS pseudo-class is a keyword added to a selector that specifies a special state of the selected element(s). For example, :hover can be used to change a button’s color when the user’s pointer hovers over it.

Think of a pseudo-class as a keyword we add to a selector to style a special state of an element.

Example: The :link pseudo-class targets links that have not been visited by the user:

Common Data Types

A data type is a type of CSS value.

Colors are an example of a data type.
Integers, numbers, and percentages are other common data types.
Images are another data type.

Length Units

Pixel Units

Absolute, don’t scale.

CSS “px” is an abstract reference unit, is not based on actual size of pixels on a device. Higher pixel density displays will rescale pixel values.

Relative Units

Relative length units are relative to other length values.

em unit

The most commonly used relative unit is the em unit. The em is known as a font-relative unit because it’s calculated based on a parent element’s font size.

1em = font-size value of parent element.

Default font size value for most browsers is 16px.

If we set our body’s font-size value to 1em:

This is equivalent to setting the font-size value to:

Tangent on parent element from a Treehouse comment. Somebody asks:

In the beginning, Why the relative value’s parent is “body”? when we change title size, it based on the size of body?

and they get the reply:

The element with the class of “title” is a <span> that has the <header> as a direct parent. It is in turn a child of the <body> element. The reference for font size is always based on the direct parent, but in a case of nesting like this, the properties are passed down from level to level.

So while the body isn’t the direct parent, changes made to it would affect the “title” span as long as they were not overridden in the immediate parent (the header).

This is elaborated in the video. The instructor changes the body font size and the title size with an em font-size scales up accordingly.

rem unit

The rem unit is similar to the em unit. The difference is that rem is relative only to the root element of the page. This gets us around the compounding font size issue we experience with em units.

Which one should we use?
– Pixels are more precise, easier to understand, and predictable
– Use %, em, or rem for designs that need to scale and adapt fluidly across different devices and screen sizes

Styles/Values/Properties

Color values

Color plays an important role in web design. With CSS, we can describe a color value in different ways. The three most common ways are with a keyword, a hexadecimal value, or an RGB function. You can also use RGBa values for transparency.

Hexadecimal values.

Hexadecimal values can be abbreviated to 3 characters if the characters are 3 sets of identical pairs as in the example above. You could therefore represent the above value as #f03.

RGB Values

RGBa Values

Text Styles

Text has a significant effect on how we view a web page.

text-align
Let’s us control the horizontal alignment of text.

text-transform
Changes the case of text – whether it’s uppercase, lowercase, or capitalized.

text-decoration
Sets the line decoration of elements. We’ll commonly use this property to remove underlines in links.

font-weight
Sets how thick or thin the characters are displayed. Some fonts let you use numeric weights from 100 to 900. Whether you can make use of these values depends on the font.

Font Properties

Like text properties, font properties let us change the appearance of text by assigning a font family, font size, font style, and more.

There are two types of font-family names. Names of specific family (e.g. Helvetica) and a generic family name (like monospace).

CSS font stacks are prioritized lists of fonts that the browser will cycle through until it finds a font that is installed on the user’s system. You need a list because not everyone has all the same fonts installed.

font-family
Defines a typeface for our text.

font-style
Allows italic or oblique faces to be selected within a font family.

Line Height

With the line-height property, we can increase, or decrease, the vertical gaps between lines of text. Line-height properties generally just use a number and don’t specify units.

We’ll commonly use the line-height property in the body element to set the overall line-height of the page. For example:

The browser multiplies the font size of each element by 1.5 to determine their line height.

font
A shorthand property that lets us write all the font properties in one value.

Box Model

Each element on a page can be thought of as a rectangular box that takes up a certain amount of space.

Elements are displayed two ways. Every element has a display value, depending on what type of element it is.

Padding vs. Margin

Padding

Keeping box model in mind, padding is space between element and the border of the “box” for that element. E.g. if you have some text with a border around it, adding some padding will increase the amount of space between the text and the border.

No padding set for this specific element (there might be some default padding values, I dunno):

5px of padding for this element:

20px of padding:

Defining Values

We can define values for padding as any length or a percentage unit. There are two ways we can set the values for padding. The first way is setting each property individually:

We can also use the shorthand property for padding, which lets us set the padding on all four sides in one declaration:

The order of the values is: Top, Right, Bottom, Left. Think clockwise.

Margin

Space outside the element’s box. Below I don’t have any padding set for the Background element:

and below I have 50px margin set:

Defining Values

The same order of padding shorthand values applies to the margin property.

This is exactly the same as writing out the full margin declarations:

Block elements

Form a separate block that takes up the full width available based on the width of its parent element. Creates new line before and after the element. Some examples: divs, paragraphs, heading tags, list items.

In-line elements

Only take up as much width as they need to. Don’t force new lines. Some examples: anchor elements, span tags, images.

Display Property

You can change how elements are displayed (turning links into block elements, for example) using the display property.

One notable value for display is inline-block, which is a sort of hybrid that gives an element both some in-line attributes and some block-like attributes (such as the ability to set top and bottom margins).

Borders

border-width
Sets the width of a border.

border-style
Sets the style of the element’s borders.

border-color
Sets the color of a border.

border
Shorthand property for setting the individual border property values in one place.