(struct name (field1 field2 ...))
- Creates a new structured type,
with methods named name
, name?
name-field1
, name-field2
,
and so on and so forth.
a. Start DrRacket.
b. Make sure that you have the latest version of the loudhum
package
by opening a terminal window and typing /home/rebelsky/bin/csc151/update
.
(Alternately, select File > Install Package…, enter
“https://github.com/grinnell-cs/loudhum.git
” and follow the instructions.)
c. Don’t forget to add (require loudhum)
to the definitions pane.
d. If we did not review the self checks at the start of class, review the self checks with your partner.
As long as we’re representing dates, we should probably take the
time to represent times. Create a structured type, time
, with
three fields: hours, minutes, and seconds. You need not add the
husk to times (at least not yet).
a. Write a procedure, (time->string atime)
, that takes a time as
a parameter and returns the time as a string of the form
HH:MM:SS
.
b. Write a procedure (string->time str)
, that takes a string of the
form HH:MM:SS
as a parameter and returns a time structure.
Chirp is a new Internet startup that lets you sent notes to your
friends, which they call “chirps”. (Creativity is not their strong
suit.) Create a structured type, chirp-kernel
, with the following
fields.
id
, a symbol we’ll use to identify the chirp.author
, a string that identifies the author of the chirp.contents
, a string that contains the body of the chirp.tags
, a list of stringsdate
, a date that represents when the chirp was chirped.time
, a time that represents the time the chirp was chirped.Create a procedure, (chirp author contents tags date time)
, that
takes four parameters, verifies their types, and then creates a
chirp kernel using those four parameters. What about the identifier?
You should generate that automatically with (gensym "chirp")
.
(gensym
is a procedure that generates a unique symbol.)
One outstanding question that we had with date
and date-kernel
was how we prevent the client from using date-kernel
, rather than
date
. In this exercise, we’ll explore one approach.
a. At the end of the corresponding reading, we
described a husk-and-kernel-style technique for ensuring that our dates
had a particular form. Copy that code into a new DrRacket window.
Make sure to include date->string
and string->date
, too.
b. Add the following to the top of the file (after the #lang racket
).
These commands tell Racket which procedures and values that are defined
in the file are accessible to other programs.
(provide date
date?
date-year
date-month
date-day
date->string
string->date)
c. Save the file as “/home/username/Desktop/dates.rkt
”, substituting
your own username.
d. Open a new DrRacket window and type the following at the
top (after the #lang racket
) and then click Run. (Once
again, you should substitute your own username.)
(require (file "/home/username/Desktop/dates.rkt"))
e. What do you expect to get when you type the following in the interactions pane of the new windows.
> (define date1 (date 2019 03 01))
?
> date1
?
> (define date2 (date 2019 22 01))
?
> date2
?
f. Check your answer experimentally.
g. You should have seen that date1
is a date-kernel
structure and that
date2
does not exist because the second call to date
is invalid.
Since date1
is valid, we should be able to extract its fields.
What do you expect the results of the following to be?
> (date-year date1)
?
> (date-month date1)
?
> (date-day date1)
?
> (date? date1)
?
h. Check your answer experimentally.
i. We’ve seen that date1
is a date-kernel
structure.
> date1
#<date-kernel>
What do you expect the result of the following to be?
> (date-kernel? date1
?
> (date-kernel-year date1)
?
> (date-kernel-month date1)
?
> (date-kernel-day date1)
?
j. Check your answer experimentally.
k. What do you expect to happen if we try to create a date with
date-kernel
?
> (define date3 (date-kernel 2019 03 01))
> date3
l. Check your answer experimentally.
m. What does this exercise suggest?
Typically, we want more than one of any struct we create. Consider,
for example, the chirp
structure we designed earlier. In effect,
the Chirp service creates something like a list of chirps. So let’s
store them as a list.
> (define chirp-list
(chirp "grinco" "We have installed Chirp on campus."
(list "grinnell" "chirp")
(date 2019 02 27) (time 11 03 00))
(chirp "grinco" "We are so cutting edge!"
(list "grinnell" "chirp")
(date 2019 02 27) (time 11 04 00))
(chirp "rebelsky" "I love CSC 151." (list "strange" "csc")
(date 2019 03 01) (time 10 00 15))
(chirp "rebelsky" "That wasn't me." (list "strange" "other")
(date 2019 03 01) (time 10 01 23))
(chirp "rebelsky" "I think my son hacked my chirpstream."
(list "strange" "paranoid")
(date 2019 03 01) (time 10 01 55))
(chirp "kington" "Welcome to GrinCo!" (list "grinnell" "raykay")
(date 2019 02 28) (time 15 02 05))
(chirp "kington" "I love CSC 151." (list "strange" "csc" "raykay")
(date 2019 03 01) (time 10 01 55))
(chirp "rebelsky" "I think my son hacked President Kington's chirpstream."
(list "paranoid")
(date 2019 03 01) (time 10 03 00))
(chirp "grinco" "We are shutting down Chirp on campus"
(list "grinnell" "chirp")
(date 2019 03 01) (time 11 03 00)))
a. Write an expression that identifies all of the chirps from rebelsky
and creates a list of their contents
> (map chirp-contents (filter _________ chirp-list))
b. Write an expression that determines how many chirps in the list
are by kington
. (Recall that (tally lst pred?)
counts the number
of values in a list that meet a particular predicate.
One of the disadvantages of lists is that they are relatively slow to search. That’s one of the reasons we use hash tables instead. For example, we might hash chirps by their unique identifier.
Write a procedure, (store-chirp! hash chrp)
that stores
a chirp in a hash table.
> (define chirps (hash-new))
> (define sample (chirp "someone" "something" (list "chirp")
(date 2019 02 28) (time 20 21 22)))
> (hash-has-key? chirps 'chirp108319)
#f
> (store-chirp! hash sample)
> (hash-has-key? chirps 'chirp108319)
#t
> (chirp-contents (hash-ref chirps 'chirp108319))
"something"
If you find that you have extra time, you might consider attempting one or more of the following exercises.
Rewrite the time
struct using a husk-and-kernel approach that
ensures that the hours, minutes, and seconds are reasonable.
Write a procedure, (time-before? time1 time2)
, that returns
true (#t
) if time1
comes before time2
and false otherwise.
Write a procedure (chirp->string chrp)
, that takes a chirp
as
a parameter and creates a dstring that represents it in a useful
way.
> (define mychirp
(chirp "rebelsky" "I love CSC 151." (list "strange" "csc")
(date 2019 03 01) (time 10 00 15)))
> (display (chirp->string mychirp))
Output! chirp12312: At 10:00:15 on 2019-01-01, rebelsky said "I love CSC 151".
This lab was (mostly) newly written in spring 2019.
The Preparation section was taken from some other lab. (Most labs have the same preparation section.)