While our main goals in this course are for you to develop your skills in “algorithmic thinking” and apply algorithmic techniques to problems in the digital humanities, you will find it equally useful to learn how to direct computers to perform these algorithms. Programming languages provide a formal notation for expressing algorithms that can be read by both humans and computers. We will use the Racket programming language, a dialect of the Scheme programming language, itself a dialect of the Lisp programming language, one of the first important programming languages.
One thing that sets these languages apart from most other languages is a simple, but non-traditional, syntax. To tell the computer to apply a procedure (subroutine, function) to some arguments, you write an open parenthesis, the name of the procedure, the arguments separated by spaces, and a close parenthesis. For example, here’s how you add 2 and 3.
> (+ 2 3)
5
One advantage of this parenthesized notation is that it eliminates the
need for the reader or the computer to know a set of precedence rules
for operations. Consider, for example, the expression 2+3x5
. Do you
add first or multiply first? Different programming languages may
interpret it differently. On the other hand, we have to explicitly
state the order, writing either (+ 2 (* 3 5))
or
(* (+ 2 3) 5)
, using *
as the multiplication symbol.
> (+ 2 (* 3 5))
17
> (* (+ 2 3) 5)
25
As this example suggests, we have already started to explore both basic operations (addition and multiplication) and sequencing (through nesting) in Racket. You should keep three points in mind when writing and reading Racket expressions.
+
that you would normally put between arguments.Of course, you can use Racket for more than arithmetic computations. Here are some examples working with text.
We can find the length of a string.
> (string-length "Jabberwocky")
11
We can break a string apart into a list of string.
> (string-split "Twas brillig and the slithy toves" " ")
'("Twas" "brillig" "and" "the" "slithy" "toves")
We can find out how many words there are once we’ve split it apart.
> (length (string-split "Twas brillig and the slithy toves" " "))
6
This operation returned a list, an ordered collection of values. Note
that lists are also surrounded by parentheses. Racket distinguishes
lists, which should not be evaluated, from expressions, which should be
evaluated, by including a tick mark, '
, before the parenthesis in most
lists.
Once we have a list of words, we can find out how long each word is.
> (map string-length
(string-split "Twas brillig and the slithy toves" " "))
'(4 7 3 3 6 5)
We can even split in strange ways, such as at the vowels. (We’ll
explain the strange #px"[aeiou]"
in a subsequent
reading.)
> (string-split "Twas brillig and the slithy toves" #px"[aeiou]")
'("Tw" "s br" "ll" "g " "nd th" " sl" "thy t" "v" "s")
You’ve already seen a few of Racket’s basic types. Racket supports numbers, strings (text), and lists of values. Of course, these are not the only types it supports. Some additional types are available through separate libraries. For example, it is comparatively straightforward to get Racket to draw simple shapes.
> (circle 15 'outline "blue")
> (circle 10 'solid "red")
We can also combine shapes by putting them above or beside each other.
> (above (circle 10 'outline "blue")
(circle 15 'outline "red"))
> (beside (circle 10 'solid "blue")
(circle 10 'outline "blue"))
> (above (rectangle 15 10 'solid "red")
(beside (rectangle 15 10 'solid "blue")
(rectangle 15 10 'solid "black")))
As you may have discovered in your youth, there are a wide variety of interesting images we can make by just combining simple colored shapes. You’ll have an opportunity to do so in [the corresponding lab].
Make a list of five or so procedures you’ve encountered in this reading, the number and types of the parameters (e.g., do they require numbers or strings), and their behavior.
Predict the output for each of the following expressions. Be prepared to discuss them in class.
(* (+ 4 2) 2)
(- 1 (/ 1 2))
(string-length "Snicker snack")
(string-split "Snicker snack" "ck")
(circle 10 'solid "teal")
Consider the expression 3-4x5-6
.
If we did not have rules for order of evaluation, one possible way to
evaluate the expression would be to subtract six from five (giving us
negative one), then subtract four from three (giving us negative
one), and then multiply those two numbers together (giving us one).
We’d express that in Racket as (* (- 5 6) (- 3 4))
.
a. What is the “official” way to evaluate that expression?
b. How would you express that in Racket?
c. Come up with at least two other orders in which to evaluate that expression.
d. Express those other two orders in Racket.